在导入之前,我正在尝试动态重写pywin32 win32com.client模块,下面的代码似乎有效--但我不满意导入的6行代码(在最后的注释之后)。有人能推荐一种更简洁的方法来创建/导入结果模块(包)吗?
import sys, ast, types
import os.path
import importlib.util
import win32com
# import ast
_win32com_client_spec = importlib.util.find_spec("win32com.client")
_win32com_client_ast = ast.parse(open(_win32com_client_spec.origin).read())
(_win32com_client_dispatch_ast,) = (x for x in _win32com_client_ast.body if isinstance(x, ast.FunctionDef) and x.name == 'Dispatch')
# rename Dispatch
_win32com_client_dispatch_ast.name = '_OldDispatch'
# create new Dispatch
_my_dispatch_mod_ast = ast.parse("""
def Dispatch(*args, **kwds):
base_inst = _OldDispatch(*args, **kwds)
spec_inst = _OldDispatch(base_inst)
return spec_inst
""")
(_my_dispatch_ast,) = _my_dispatch_mod_ast.body
# insert new Dispatch in module
_win32com_client_ast.body.insert(_win32com_client_ast.body.index(_win32com_client_dispatch_ast)+1, _my_dispatch_ast)
# import the package
_my_win32com_client_co = compile(_win32com_client_ast, '<patched win32com.client>', 'exec')
_my_win32com_client_mod = types.ModuleType('win32com.client')
_my_win32com_client_mod.__path__ = (os.path.dirname(_win32com_client_spec.origin),)
sys.modules[_my_win32com_client_mod.__name__] = _my_win32com_client_mod
win32com.client = _my_win32com_client_mod
exec(_my_win32com_client_co, _my_win32com_client_mod.__dict__)发布于 2022-03-26 15:46:12
进一步阅读文档说明使用ModuleSpec对象比使用types.ModuleType更可取。
参考文献:https://docs.python.org/3/library/importlib.html#importlib.util.module_from_spec
生成的代码隐式地处理包的__path__,并允许在整个过程中重用spec对象。请注意,如果使用规范原点显示补丁如下,则文件属性应显式设置如下。
模块应该在执行之前导入,这对于子模块导入来说似乎很重要,就像在gencache模块(例如import win32com.client.CLSISToClass )中发现的那样
import sys, ast
import importlib.util
import win32com
if 'win32com.client' not in sys.modules:
# import ast
_win32com_client_spec = importlib.util.find_spec("win32com.client")
_win32com_client_path = _win32com_client_spec.origin
_win32com_client_spec.origin = '<patched win32com.client>'
_win32com_client_ast = ast.parse(open(_win32com_client_path).read())
# rename Dispatch
(_win32com_client_dispatch_ast,) = (x for x in _win32com_client_ast.body if isinstance(x, ast.FunctionDef) and x.name == 'Dispatch')
_win32com_client_dispatch_ast.name = '_OldDispatch'
# create new Dispatch (disregard line numbers)
_my_dispatch_mod_ast = ast.parse("""
def Dispatch(*args, **kwds):
base_inst = _OldDispatch(*args, **kwds)
spec_inst = _OldDispatch(base_inst)
return spec_inst
""")
(_my_dispatch_ast,) = _my_dispatch_mod_ast.body
# insert new Dispatch in module
_win32com_client_ast.body.insert(_win32com_client_ast.body.index(_win32com_client_dispatch_ast)+1, _my_dispatch_ast)
# compile (original path for debugging), create, import and exec the module
_my_win32com_client_co = compile(_win32com_client_ast, _win32com_client_path, 'exec')
_my_win32com_client_mod = importlib.util.module_from_spec(_win32com_client_spec)
_my_win32com_client_mod.__file__ = _win32com_client_path
win32com.client = sys.modules['win32com.client'] = _my_win32com_client_mod
try:
exec(_my_win32com_client_co, _my_win32com_client_mod.__dict__)
except:
del win32com.client, sys.modules['win32com.client']
raisehttps://stackoverflow.com/questions/71627631
复制相似问题