python (3.2) - ftplib 和“unicode”文件名

问题描述 投票:0回答:1

情况: 我有一个小型 NAS 服务器,支持 FTP、SHH、Samba(和其他)协议。 我想制作 python 脚本,通过 FTP 将文件从“源目录”(从桌面 PC - Windows 7)复制到 NAS 上的“目标目录”。

问题: ftp.mkd(“安德烈”) 制作正确的uft-8目录

  1. 我无法用total Commander ftp打开这个目录
  2. 我无法在 Windows 资源管理器中打开此目录(98.168.X.Y\destination-directory\Adnré)
  3. SSH:ls 命令显示“André”

总指挥: 当我创建同一目录“André”时

  1. 总计c。 - 无障碍
  2. 窗户 - 无障碍
  3. SHH:ls 命令显示“André”(好吧,这不是问题)

解决方案: 如何将“André”转换为“André”?在将字符串传递给 ftp.mkdir() 之前,我必须对它做什么? (脚本采用utf-8)

python ftplib
1个回答
0
投票

问题

这似乎是 Unicode 字符串规范化的问题。

Unicode 通常允许相同的字符由不同的底层二进制序列表示。例如,“é”(e-acute)可以用单个代码点 U+00E9(带有锐音符号的拉丁小写 e)表示,也可以用两个代码点序列 U+0065(拉丁小写 e)U+0301(组合)表示尖锐的口音)。

>>> 'Andr\u00E9'
'André'
>>> 'Andr\u0065\u0301'
'André'

它们看起来相同,并且根据 Unicode 规范,它们都是表示 e-acute 的可接受方式,但您可以在幕后看到二进制表示不同。

>>> bytes('Andr\u00E9', 'utf-8')
b'Andr\xc3\xa9'
>>> bytes('Andr\u0065\u0301', 'utf-8')
b'Andre\xcc\x81'

解决方案

您需要规范化底层表示。 Unicode 提供四种不同的标准化形式:NFD、NFC、NFKD 和 NFKC。

D 形式将字符分解为多个码点形式,C 形式将字符组合为单码点形式。

K 代表兼容性(因为 C 已经被用来代表组合)。 K 形式会将连字分解为单独的字符,因此您几乎肯定要使用 K 形式(尽管它对于您的“André”示例似乎没有什么区别)。

至于 C 和 D 形式之间的选择,回想一下我们之前在使用 e-acute 的组合单码点形式时看到的二进制输出:

>>> bytes('Andr\u00E9', 'utf-8')
b'Andr\xc3\xa9'

并注意 U+00C3 = à 且 U+00A9 = ©

它仍应显示为“André”而不是“André”,但这是软件的一个单独问题,该软件要么不支持 Unicode,要么其编码设置配置错误。

重要的一点是,如果您想要“André”行为,则应该使用 C 形式进行规范化。

简而言之,使用NFKC形式进行标准化。

代码

要在 Python 中执行此操作,请使用

unicodedata.normalize
:

>>> from unicodedata import normalize
>>>
>>> bytes(normalize('NFKC', 'Andr\u00E9'), 'utf-8')
b'Andr\xc3\xa9'
>>> bytes(normalize('NFKC', 'Andr\u0065\u0301'), 'utf-8')
b'Andr\xc3\xa9'

或者,就您而言:

from unicodedata import normalize

ftp.mkd(normalize('NFKC', 'André'))
© www.soinside.com 2019 - 2024. All rights reserved.