fal*_*tru 54 python python-3.x python-3.3
如何.py
在Python 3.3+中导入任意python源文件(其文件名可以包含任何字符,并不总是以其结尾)?
我使用imp.load_module
如下:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Run Code Online (Sandbox Code Playgroud)
它仍然适用于Python 3.3,但根据imp.load_module
文档,它已被弃用:
从版本3.3开始不推荐使用:不需要使用加载器来加载模块,并且不推荐使用find_module().
和imp
模块文档建议使用importlib
:
注意新程序应使用importlib而不是此模块.
在不使用已弃用的imp.load_module
函数的情况下,在Python 3.3+中加载任意python源文件的正确方法是什么?
fal*_*tru 53
从importlib
测试代码中找到解决方案.
使用importlib.machinery.SourceFileLoader:
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Run Code Online (Sandbox Code Playgroud)
注意:仅适用于Python 3.3+.
Loader.load_module
自Python 3.4起,不推荐使用UPDATE.Loader.exec_module
改为使用:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
Run Code Online (Sandbox Code Playgroud)
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Run Code Online (Sandbox Code Playgroud)
Ste*_*fke 18
更短版本的@falsetrue解决方案:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Run Code Online (Sandbox Code Playgroud)
我用Python 3.5和3.6测试了它.
根据评论,它不适用于任意文件扩展名.
类似于@falsetru但是对于Python 3.5+并且考虑了importlib
doc使用importlib.util.module_from_spec
的内容types.ModuleType
:
此函数[
importlib.util.module_from_spec
]优于使用types.ModuleType
创建新模块,因为spec用于在模块上设置尽可能多的导入控制属性.
我们可以importlib
通过修改importlib.machinery.SOURCE_SUFFIXES
列表单独导入任何文件.
import importlib
importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()
Run Code Online (Sandbox Code Playgroud)
importlib
辅助功能
这是一个方便的、随时可用的帮助器来替换imp
,并带有示例。技术与/sf/answers/1330788161/相同,只是提供了一个更方便的功能。
主文件
#!/usr/bin/env python3
import os
import importlib
def import_path(path):
module_name = os.path.basename(path).replace('-', '_')
spec = importlib.util.spec_from_loader(
module_name,
importlib.machinery.SourceFileLoader(module_name, path)
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
sys.modules[module_name] = module
return module
notmain = import_path('not-main')
print(notmain)
print(notmain.x)
Run Code Online (Sandbox Code Playgroud)
非主要
x = 1
Run Code Online (Sandbox Code Playgroud)
跑:
python3 main.py
Run Code Online (Sandbox Code Playgroud)
输出:
<module 'not_main' from 'not-main'>
1
Run Code Online (Sandbox Code Playgroud)
我替换-
为_
因为我没有扩展名的可导入 Python 可执行文件有连字符,如my-cmd
. 这不是强制性的,但会产生更好的模块名称,例如my_cmd
.
这种模式也在文档中提到:https : //docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly
我最终转向它,因为在更新到 Python 3.7 后,import imp
打印:
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
Run Code Online (Sandbox Code Playgroud)
我不知道如何关闭它,这是在以下位置询问的:
在 Python 3.7.3 中测试。
归档时间: |
|
查看次数: |
19541 次 |
最近记录: |