tot*_*two 7 python python-importlib python-3.5
我的问题类似于如何在给定完整路径的情况下导入模块?但是,我没有导入.py源文件,而是导入了带有.pyd的程序包。
在运行时,我根据一些动态生成的c代码创建新的软件包模块。我成功生成了包含__init__.py文件和F的软件包Foo mod.pyd:
/a/temp/dir/foo/
__init__.py
bar.pyd
Run Code Online (Sandbox Code Playgroud)
我正在使用的示例代码是
import importlib.util
spec = importlib.util.spec_from_file_location("foo.bar", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.bar()
Run Code Online (Sandbox Code Playgroud)
如果我尝试从pyd 使用spec_from_file_location('foo.bar', '/a/temp/dir/foo/__init__.py')模块bar,则无法加载。
如果我尝试使用,spec_from_file_location('foo.bar', '/a/temp/dir/foo/')则spec_from_file_location返回None。
如果尝试使用spec_from_file_location('foo.bar', '/a/temp/dir/foo/bar.pyd'),则会出现以下错误堆栈:
File "<frozen importlib._bootstrap>", line 577, in module_from_spec
File "<frozen importlib._bootstrap_external>", line 903, in create_module
File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
ImportError: DLL load failed: A dynamic link library (DLL) initialization routine failed.
Run Code Online (Sandbox Code Playgroud)
推荐的4行importlib解决方案的替代方法是为MetaPathFinder和创建具体的类SourceLoader。我的以下MetaPathFinder工作正常,但是,我不确定如何Loader正确实施。get_data返回值需要python代码的Unicode表示形式。如何返回加载程序中的包结构或pyd内容?
class MyLoader(importlib.abc.SourceLoader):
def __init__(self, fullname, path, pyd):
self.path = path
self.fullname = fullname
self.pyd = pyd
def get_data(self, path):
print('*** get_data', path)
with open(os.path.join(self.path, self.pyd), 'r') as f:
return f.read()
def get_filename(self, fullname):
print('*** get_filename', fullname)
return os.path.join(self.path, '__init__.py')
def is_package(self):
return True
class MyFinder(MetaPathFinder):
def __init__(self, this_module, workdir, pyd):
self._this_module = this_module
self._workdir = workdir
self._pyd = pyd
def find_spec(self, fullname, path, target=None):
print('find_spec', fullname, path, target, self._this_module)
if fullname != self._this_module:
return
filename = os.path.join(self._workdir, self._this_module)
spec = ModuleSpec(
name = fullname,
loader = MyLoader(fullname, filename, self._pyd),
origin = filename,
loader_state = 1234,
is_package = True,
)
return spec
def is_package(self):
return True
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
908 次 |
| 最近记录: |