Reputation:
Long story short, I'm making a program that writes a whole bunch of Unicode to a file. It does this by using the Tkinter asksaveasfile
dialog to let the user choose where they want to save it. Here's the offending snippet (By the way, I imported tkinter.filedialog
as fudder
just for fun.):
name = fudder.askopenfilename(defaultextension =("Python Files","*.py"),title = "Choose a file to encrypt.")
with open(name,'r') as Usefile:
filecont = Usefile.read()
if filecont is None:
return
else:
result = crypt(filecont)
with fudder.asksaveasfile(mode = 'w', defaultextension = '.txt', title = 'Save the decrypted file.') as newf:
if result is None:
return
else:
newf.write(result[0].encode('utf-8'))
newf.write('\n\n\nKey:\n\n\n')
newf.write(result[1].encode('utf-8'))
newf.close()
I looked at several SO questions like this one, but none of them addressed this in particular. The asksaveasfile
dialog works just like the open
function, but I can't specify the encoding. I tried to encode it to bytes, but you can only write strings to a file, and you can't convert the bytes to a string and then convert it back to bytes.
Upvotes: 2
Views: 3603
Reputation: 19174
I checked the code for asksaveasfile
and indeed it only passes the filename and mode to open. It is strictly a convenience function combining a call to asksaveasfilename
with a call to open(filename, mode)
, with all other args defaulted. So don't use it.
Instead, use asksaveasfilename
and explicitly open the file yourself, just as you did for for the source file. You can then write the open call you want, with encoding='utf-8'
and any other non-default options.
The first with
should end after you have read Usefile
and have no further need of it. The if
statement should therefore be dedented.
Upvotes: 6
Reputation: 87134
Assuming that you are using Python 3 (tkinter.filedialog
strongly suggests that you are), the file will be opened with the locale encoding as returned by locale.getpreferredencoding()
. If that is already UTF-8 then you should be able to write directly to the file without explicitly encoding the strings.
However, because you are encrypting the file, crypt()
probably returns a bytes
string, not a str
(unicode) string. If this is the case then you should open the input and output files in binary mode. Then no encoding is required when writing to the output file.
name = fudder.askopenfilename(defaultextension =("Python Files","*.py"),title = "Choose a file to encrypt.")
with open(name, 'rb') as Usefile:
filecont = Usefile.read()
if filecont is None:
return
else:
result = crypt(filecont)
if result is None:
return
with fudder.asksaveasfile(mode = 'wb', defaultextension = '.txt', title = 'Save the decrypted file.') as newf:
newf.write(result[0])
newf.write(b'\n\n\nKey:\n\n\n')
newf.write(result[1])
The key differences are:
crypt()
returns None
Upvotes: 2