Paine Paine - 1 year ago 65
Python Question

Printing tuples created with zip to a text file

First time using python was today, so please forgive me for being a bit rubbish. This is the base code, which I know works.

from lxml import html
import lxml
import requests

sourcepage = requests.get('')
tree = html.fromstring(sourcepage.content)

teamname = tree.xpath('descendant::table[1][@class = "table-stats"]/tbody/tr/td[@class = "team-name"]/a/text()')
position = tree.xpath('descendant::table[1][@class = "table-stats"]/tbody/tr/td[@class = "position"]/span[@class = "position-number"]/text()')
movement = tree.xpath('descendant::table[1][@class = "table-stats"]/tbody/tr/td[@class = "position"]/span[@class="moving-down" or @class="no-movement" or @class="moving-up"]/text()')
goaldiff = tree.xpath('descendant::table[1][@class = "table-stats"]/tbody/tr/td[@class = "goal-difference"]/text()')
points = tree.xpath('descendant::table[1][@class = "table-stats"]/tbody/tr/td[@class = "points"]/text()')

combined = zip(teamname,position,movement,goaldiff,points)

What it does is scrape a website, save as a tree, and turn it into a tuple (I think)

The table prints fine to the command line with

print("Pos. | Team | P | GD | Pts\n:--:|:--|:--:|:--:|:--:")
for var1,var2,var3,var4,var5 in combined:

But I've been having serious issues getting it to print to file.

I've tried the following methods:

outfile = open('output.txt', 'w')
print>>outfile("Pos. | Team | P | GD | Pts\n:--:|:--|:--:|:--:|:--:")
for var1,var2,var3,var4,var5 in combined:

This one outputs an error - TypeError: '_io.TextIOWrapper' object is not callable

with open('output.txt', 'w') as fp:
fp.write("Pos. | Team | P | GD | Pts\n:--:|:--|:--:|:--:|:--:\n")
for var1,var2,var3,var4,var5 in combined:
var1s = str(var1)
print("debug: var1 / var1s set to: ",var1,var1s) #prints nothing (?)
var2s = str(var2)
var3s = str(var3)
var4s = str(var4)
var5s = str(var5)

This only outputs the header line.

(var1a, var2a, var3a, var4a, var5a) = combined
var1a, var2a, var3a, var4a, var5a = combined

Both suprised me, as they both return a ValueError: not enough values to unpack (expected 5, got 0)

with open('output.txt', 'w') as fp:
fp.write('\n'.join('{} {} {} {} {}' % x for x in combined))

This outputs a blank file, as do

outfile = open('outfile.txt', 'w')
for t in combined:
line = ' '.join(str(x) for x in t)
outfile.write(line + '\n')


with open('output.txt', 'w') as f:
for stuff in combined:
f.write('%s %s %s %s %s\n' % stuff)

I've spent a couple of hours googling and trying to mine my way through stackoverflow questions but I'm still coming up short, and I'm a bit out of my depth here.

The reason I want to output it to file is The next step after this is to run some regex on the output to convert the truncated names used back to their proper ones, as well as wrap some reddit markup around it to turn them into links.

Answer Source

It seems like you tried to write to the file after you already printed the combined zip to console. In Python 3, zip produces a generator, i.e. it will be exhausted after you iterate it once.

>>> z = zip([1,2,3],[4,5,6])
>>> list(z)
[(1, 4), (2, 5), (3, 6)]
>>> list(z)

Either convert the generator to a list first, i.e. combined = list(zip(...)) or just remove the print-to-console part, if you do not need it.

Once this is fixed, any of the ways to write the values to file should work -- except the first one. The print >> outfile(params) syntax from Python 2 is illegal in Python 3. What this tries to do would be to call outfile with params (thus not-callable-exception) and then right-shift >> the print function by that amount... whatever that's supposed to mean. Instead, you want print(params, file=outfile), or just use any of the other methods.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download