os.open处理含非UTF8字符文件名:源NFS正常目标NFS报无效参数
问题
尝试将文件从源NFS卷复制到目标NFS卷,文件名包含非UTF8字符,使用字节类型进行open/read/write操作。os.open可以正常打开源路径,但在目标路径上触发无效参数错误。最简复现示例如下:
>>> import os >>> x = b'/x/en/local/noarch/agnostic/docs/FSques\x8awithrepl.doc' >>> os.open(x, os.O_RDONLY) 3 >>> fd = os.open(x, os.O_RDONLY) >>> os.path.getsize(fd) 37888 >>> >>> y=b'/mnt/x/dest/WAFSquestionnai\x8awithreplies.doc' >>> os.open(y, os.O_RDONLY) Traceback (most recent call last): File "<stdin>", line 1, in <module> OSError: [Errno 22] Invalid argument: b'/mnt/x/dest/WAFSquestionnai\x8awithreplies.doc' >>> import cchardet as ct >>> ct.detect(x) {'encoding': 'ISO-8859-3', 'confidence': 0.7991858124732971} >>> >>> ct.detect(y) {'encoding': 'ISO-8859-3', 'confidence': 0.8912176489830017} >>> >>> import sys >>> sys.getdefaultencoding() 'utf-8' >>>
为何os.open在源路径成功却在目标路径失败?为何得到的不是FileNotFound错误?
解答
- NFS服务器编码配置差异:源和目标NFS卷的服务器挂载配置不同。源NFS服务器兼容ISO-8859-3这类非UTF-8编码的文件名,能正常解析路径;而目标NFS服务器可能强制要求文件名必须是UTF-8编码,无法识别
\x8a这类非UTF-8字节,直接返回无效参数错误。 - 字节路径的系统调用逻辑:Python传入字节路径时,会直接把字节序列交给系统调用。不同NFS服务器的实现对非UTF-8字节序列的兼容性不同——源服务器的实现支持ISO-8859-3编码,所以能找到文件;目标服务器不支持该编码,判定路径字节序列无效,抛出
Errno 22。 - 错误类型差异的原因:
FileNotFound错误需要服务器先成功解析路径,再检查文件是否存在后返回。但目标服务器在解析路径阶段就判定字节序列无效,直接终止操作,根本没到检查文件存在性的环节,因此不会返回FileNotFound。
内容的提问来源于stack exchange,提问作者CodeTry
相关产品推荐
相关产品推荐

