注意:我知道正确的解决方案就是执行
pip install pywin32
并让一切自动完成,但这里的问题是关于 pythoncom
的内部结构。
当做
import pythoncom
时,它有效,但是:
在“C:\Python38\Lib\site-packages\pythoncom.py”中,有
import pywintypes
,但site-packages
目录中不存在pywintypes.py或.pyd或.dll。它怎么能“神奇”地找到
pywintypes
?
print(pythoncom.__file__)
时,我们看到:
'C:\\Python38\\lib\\site-packages\\pywin32_system32\\pythoncom38.dll'
这种令人惊叹的行为在内部是如何实现的? (即我们导入的 pythoncom.py 现在被识别为另一个文件,.dll)
pythoncom.py
包含:
# Magic utility that "redirects" to pythoncomxx.dll
import pywintypes
pywintypes.__import_pywin32_system_module__("pythoncom", globals())
这个(我引用的)重定向到pythoncomxx.dll
的“神奇实用程序”是什么以及在哪里?仅执行
import pythoncom
操作时,我看不到该实用程序在哪里被调用。
pywintypes.__import_pywin32_system_module__
_win32sysloader
的结合。
DLL 路径在此构建(其中 modname 为“pythoncom”):
suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else ""
filename = "%s%d%d%s.dll" % (
modname,
sys.version_info[0],
sys.version_info[1],
suffix,
)
它被传递给_win32sysloader:
found = _win32sysloader.LoadModule(filename)
这是一个 C++ 文件,加载 DLL:
HINSTANCE hinst = LoadLibraryEx(modName, NULL,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
最终结果是加载的DLL的路径,它被注册为Python模块这里:
# Load the DLL.
loader = importlib.machinery.ExtensionFileLoader(modname, found)
spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=found)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
至于为什么是pywintypes,应该在Lib/site-packages/win32/lib/pywintypes.py
>>> import pywintypes
>>> sys.modules['pywintypes']
<module 'pywintypes' (C:\Python312\Lib\site-packages\pywin32_system32\pywintypes312.dll)>
但那是因为 pywintypes
使用自己的
__import_pywin32_system_module__
函数来替换自己:
__import_pywin32_system_module__("pywintypes", globals())