Reputation: 129
I've tested the code below, everything does as I expected it to except line 29. The final.write(invrow) doesn't actually write to the file. When I use a simple print invrow, it displays with no problems. I get no errors, what's happening here? What am I missing? What am I not doing properly?
import csv
inv = csv.DictReader(open('ireport.txt', 'rU'), dialect='excel-tab', delimiter="\t")
vbr = csv.DictReader(open('vb.txt', 'rU'), dialect='excel-tab', delimiter="\t")
mainr = csv.DictReader(open('main.txt', 'rU'), dialect='excel-tab', delimiter="\t")
final = open('ireport2.tab', 'w')
inva = []
maina = []
vba = []
for row in inv:
inva.append(row)
for row in mainr:
maina.append(row)
for row in vbr:
vba.append(row)
for invrow in inva:
for mainrow in maina:
try:
if invrow['\xef\xbb\xbfPART_CODE'] == mainrow['PART CODE']:
invrow['MAINQTY'] = mainrow['ON-HAND']
print invrow # works
final.write(invrow) #doesn't work. Why?
except TypeError:
pass
except ValueError:
pass
final.close()
Upvotes: 2
Views: 637
Reputation: 1734
I don't really think this is it, but since others gave good answers, you might as well need this one as final desperate fix.
I managed to get a similar bug weeks ago, also working with txt files. As far as i know you can't save some unicode/ascii/others symbols into txt files, such as ♥☻☺♦♣♠ on specific circunstances, i'll show you 2 examples:
1: This would crash it:
printablelog = open("examplefile.txt", "a")
printablelog.write("An example ♥☻☺♣ とかちそのラヒイスハレラテ and more text")
printablelog.close()
2: this would save it in bytes and since it encode it that way, you won't get errors:
printablelogfixed = open("example.txt", "ab")
printablelogfixed.write(bytes("An example ♥☻☺♣ とかちそのラヒイスハレラテ and more text", 'UTF-8'))
printablelogfixed.close()
Good luck.
Upvotes: 0
Reputation: 141
You would just need to call toString() or a similar method on the object you're trying to write. Some languages would implicitly convert it to a writeable object, but you'll need to be more explicit with Python.
Upvotes: -1
Reputation: 366213
print
automatically calls str
on each argument. write
does not.
So, if you pass a string, they'll both work, and in fact do the exact same thing. But if you pass something different, write
will raise a TypeError: expected a character buffer object
.
In your case, invrow
is a dictionary, as returned by csv.DictReader
. That's not a string, so you'll get the TypeError
.
The reason you get no errors is that you're explicitly catching and throwing away TypeError
s in your code, with that except TypeError: pass
code.
Meanwhile, I think what you wanted to do here is to use a csv.DictWriter
to write each row:
writer = csv.DictWriter(final, inv[0].keys())
Then:
writer.writerow(invrow)
As a side note, you could simplify this tremendously. For example, a DictReader
is an iterable; if you want to make a list of it, just call list
on it, don't loop over it and append
one by one. Like this:
inva = list(inv)
maina = list(main)
vba = list(vb)
But really, you only need to change the "inner" one, maina
, into a list
; the outer one, inva
, you can just loop directly over the DictReader
. And vba
, you never use at all.
Also, if you use a with
statement, you don't need the explicit close
. And this has the side benefit that if your program quits in the middle with an exception, the file will be flushed and closed, so you can see what got written right before the error.
Finally, if you're going to use a try
/except
to handle exceptions and continue past them, you really want to have it print or log something so you know that it happened. In fact, I'd suggest leaving the try
out during initial development, until you know that it works on non-broken files, and only adding it when you start dealing with broken files.
Putting it all together:
with open('main.txt', 'rU') as mainf:
main = list(csv.DictReader(mainf, dialect='excel-tab', delimiter="\t")
with open('ireport.txt', 'rU') as invf, open('ireport2.tab', 'w') as finalf:
inv = csv.DictReader(invf, dialect='excel-tab', delimiter="\t")
final = csv.DictWriter(finalf, dialect='excel-tab', delimiter="\t",
fieldnames=inv.fieldnames)
for invrow in inv:
for mainrow in main:
if invrow['\xef\xbb\xbfPART_CODE'] == mainrow['PART CODE']:
invrow['MAINQTY'] = mainrow['ON-HAND']
final.writerow(invrow)
Upvotes: 6