ctypes.cdll.LoadLibrary()中文路径的解决方案
直接上代码
# -*- coding:utf-8 -*- import ctypes dllname = "E:\中文路径测试\BinaryDiff.dll" dll = ctypes.cdll.LoadLibrary(dllname) # 报错信息: Traceback (most recent call last): File "D:/PycharmProject/untitled/test.py", line 5, in <module> dll = ctypes.cdll.LoadLibrary(dllname) File "C:Python27Libctypes\__init__.py", line 444, in LoadLibrary return self._dlltype(name) File "C:Python27Libctypes\__init__.py", line 366, in __init__ self._handle = _dlopen(self._name, mode) WindowsError: [Error 126]
错误分析
在遇到这个错误的第一反应就是百度 WindowsError: [Error 126] 看了一圈下来,觉得和我出现的问题都不太一样,首先我可以确定dllname路径是肯定正确的,再其次我也验证了dll中的C接口的正确性。 那么错误的唯一原因就是编码的问题了,前两天刚写了一个python和编码的文章,这里就出了问题,首先我们强调一点:python内部会对字符串做decode(到unicdeo)的一个操作,然后再输出到上层的时候进行encode。 在这里我忽略了前半段的结论,所以对此报错产生了疑问。 在这里我们可以确定的是ctypes.cdll.LoadLibrary(dllname)的参数dllname是一个字符串,然而这个字符串是传给的python内部,python会先将dllname进行decode让python能识别到,然后再处理其逻辑。因为我们没有明确的指明decode的形式,这里使用了系统默认的mbsc中的ascii进行decode导致错误。由此我们可以得出下面的结论:
# -*- coding:utf-8 -*- import ctypes dllname = "E:\中文路径测试\BinaryDiff.dll" dll = ctypes.cdll.LoadLibrary(dllname.decode(utf-8)) # 报错信息 Traceback (most recent call last): File "D:/PycharmProject/untitled/test.py", line 7, in <module> dll = ctypes.cdll.LoadLibrary(dllname) File "C:Python27Libctypes\__init__.py", line 444, in LoadLibrary return self._dlltype(name) File "C:Python27Libctypes\__init__.py", line 366, in __init__ self._handle = _dlopen(self._name, mode) UnicodeEncodeError: ascii codec cant encode characters in position 3-8: ordinal not in range(128)
然而很不幸依然报错,通过报错信息我们可以知道ctypes.cdll.LoadLibrary(dllname)内部还执行了一次encode(ascii)的操作,可以知道这里函数要求传入的是一个str的对象,由于是中文我们要使用gbk(日文、韩文请选择其它形式的字符集格式),所以我们修改成下面的形式:
# -*- coding:utf-8 -*- import ctypes dllname = "E:\中文路径测试\BinaryDiff.dll" dll = ctypes.cdll.LoadLibrary(dllname.decode(utf-8).encode(gbk))
至此你会发现代码运行正常WindowsError: [Error 126] 的错误消失了。
总结:
- python内部的交互方式一定要熟记在心
- 对于python的输入输出 不能只停留在print()、write()等函数上。要深刻的认知输入输出是针对与python内还是python外。(比较绕,因为写的比较细,所以这里自己能理解就可以了)