【问题标题】:Open, close and copy of unicode files on Windows在 Windows 上打开、关闭和复制 unicode 文件
【发布时间】:2018-10-16 18:55:55
【问题描述】:

在尝试对在另一个程序中打开文件、关闭另一个程序中的文件以及执行系统操作(例如在基于 unicode 的文件名上复制文件)执行单独操作时,我遇到了以下错误。我当前的代码在 Macintosh 上运行良好,但在 Windows 上却不行。我刚开始使用 unicode 文件名和 CLI。

UnicodeEncodeError: 'ascii' codec can't encode character u'\u0301' in position 5: ordinal not in range(128)

另一个应用程序示例中的简化关闭文件如下所示:

def CloseFile( fileToClose ):
    cmd = [ 'sudo', fmsadmin, 'close', fileToClose, '-u', 'userName', '-p', 'accountName', '-y' ] 
    subprocess.check_output( cmd )

CloseFile( u'ÉürøFile.fmp12' )

我尝试在设置 cmd 变量之前执行解码,但这不起作用。

fileToClose = fileToClose.decode('utf-8')

如果你愿意,我可以给你一个 CopyFile() 示例,但是在调用命令之前就会出现错误。因此,您无需安装 FileMaker Server 即可重现该问题。

我正在使用 shutil.copy( from, to ) 作为复制方法。

【问题讨论】:

  • 如果fileToClose变量的类型是unicode,你肯定需要encode(),而不是decode()。而且我不确定 Windows 是否使用 UTF-8 作为文件名。
  • @lenz 是的,这就是我想要弄清楚的。我也尝试过 fileToClose = fileToClose.encode(sys.stdout.encoding) 但最终出现同样的错误。在编码行而不是子进程行。
  • AFAIK,STD 通道的编码与文件系统的文件名编码无关,此外,与subprocess 委托的系统调用使用的编码无关。你见过this thread吗?
  • 是的,我做到了。那里没有关于如何安装建议的补丁的建议。我尝试安装它。我还将所有代码移至 Popen 并没有解决问题。我在应用补丁时猜测,所以不确定补丁是否被使用。我采取的步骤记录在补丁页面上。
  • 如果该答案中的第一个答案是正确的,那么切换到 Python 3 可能会有所帮助。这不是一个选择吗?无论如何,你迟早要迁移到 Py3。

标签: python-2.7 unicode


【解决方案1】:

好的...我终于想通了,并将在下面提供警告。我从另一个程序中复制并粘贴了文件名。

此文件名中的前两个字符未组合 (ÉürøFile.fmp12)。所以它被编码为E´和u¨。而不是 É 和 ü。显然,Python 2.7 在尝试基于该文件名执行命令行时无法处理未组合的字符。

所以这里的警告是:

  1. 使用 Python 中的 repr() 函数了解字符串的编码方式。
  2. 使用支持所需编码样式的工具
  3. 比较值时,请确保比较的双方都支持相同的 unicode 样式(组合与分解)。
  4. 最后查找错误指向的字符。我没有……但如果我这样做了……我会发现 unicode 字符 0301 是一个重音字符。这个角色:´

作为此问题的后续行动,我发现了另一个问题。更正上面的代码后,我试图通过使用 Python 内置的 zip 实用程序来保护 unicode 文件名。将文件存储在 zip 文件中,然后在需要时使用 unicode 文件名解压缩文件。这显然是 Windows 上的 Python 2.7 中的一个错误。当 Python 内置的解压缩实用程序解压缩文件时,它会弄乱磁盘上文件名的编码(在 Mac 上工作正常)。该名称在 Windows 上被删除,并且无法被系统实用程序识别,例如使用 copy、mv、getSize 等。我的解决方法是将带有欧洲和亚洲名称的松散测试文件放在 SMB 卷上的文件夹中,并让我的代码工作而是直接在他们身上。吸取了更多的教训。我希望将来可以迁移到 Python 3,并且基于文件的问题会更少。

【讨论】:

  • 看起来这些字符是 decomposed 形式(拉丁字符后跟重音字符,所以 repr 将是 u'E\u0301u\u0308')。您可以通过 unicodedata.normalize('NFC', string) 将它们更改为 composed 形式(单个字符,如 u'\xc9\xfc')。不知道这是否会有所不同。
  • 感谢终于搞定了。我的代码实际上使用单个字符,但我使用 Macs 压缩实用程序压缩了这些文件,该实用程序可以正确压缩和解压缩它们。不幸的是,Windows 上的 Python 扩展在解压后无法正确命名磁盘上的文件。我通过不对这些类型的文件使用文件压缩来解决这个问题。也许 Python 3.x 处理得更好,但我还不能从 2.7 升级。
猜你喜欢
  • 2011-11-29
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 2016-09-07
  • 2013-09-01
  • 1970-01-01
相关资源
最近更新 更多