user1764417
user1764417

Reputation: 129

Print works, write doesn't. How come?

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

Answers (3)

Saelyth
Saelyth

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

DaveWeber
DaveWeber

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

abarnert
abarnert

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 TypeErrors 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

Related Questions