Tkinter,asksaveasfile和unicode

时间:2016-03-06 02:15:59

标签: python python-3.x unicode tkinter

长话短说,我正在制作一个程序,将一大堆Unicode写入文件。它通过使用Tkinter asksaveasfile对话框让用户选择他们想要保存的位置来实现。这是有问题的片段(顺便说一下,我将tkinter.filedialog导入为fudder只是为了好玩。):

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()

我看了几个像这样的SO问题,但没有一个特别针对这个问题。 asksaveasfile对话框的工作方式与open功能类似,但我无法指定编码。我试图将其编码为字节,但您只能将字符串写入文件,并且您无法将字节转换为字符串,然后将其转换回字节。

2 个答案:

答案 0 :(得分:3)

我检查了asksaveasfile的代码,实际上它只传递文件名和模式打开。它是一个简单的便捷函数,它将对asksaveasfilename的调用与对open(filename, mode)的调用相结合,其他所有args都是默认的。所以不要使用它。

相反,使用asksaveasfilename并自己明确打开文件,就像您对源文件所做的那样。然后,您可以使用encoding='utf-8'和任何其他非默认选项编写所需的公开呼叫。

第一个with应该在您阅读Usefile并且不再需要它之后结束。因此,if语句应缩减。

答案 1 :(得分:2)

假设您使用的是Python 3(tkinter.filedialog强烈建议您使用),将使用locale.getpreferredencoding()返回的语言环境编码打开该文件。如果它已经是UTF-8,那么你应该能够直接写入文件而无需显式编码字符串。

但是,由于您正在加密文件,crypt()可能返回bytes字符串,而不是str(unicode)字符串。如果是这种情况,那么您应该以二进制模式打开输入和输出文件。然后在写入输出文件时不需要编码。

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])

主要区别是:

  • 文件以二进制模式打开
  • 无编码
  • 如果crypt()返回None ,则不会显示
  • 保存对话框