导入任意python源文件。(Python 3.3+)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19009932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 12:32:56  来源:igfitidea点击:

Import arbitrary python source file. (Python 3.3+)

pythonpython-3.xpython-3.3

提问by falsetru

How can I import an arbitrary python source file (whose filename could contain any characters, and does not always ends with .py) in Python 3.3+?

如何.pyPython 3.3+ 中导入任意 Python 源文件(其文件名可以包含任何字符,并且并不总是以 结尾)?

I used imp.load_moduleas follows:

我使用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'>

It still works in Python 3.3, but according to imp.load_moduledocumentation, it is deprecated:

它仍然适用于 Python 3.3,但根据imp.load_module文档,它已被弃用:

Deprecated since version 3.3: Unneeded as loaders should be used to load modules and find_module() is deprecated.

3.3 版后已弃用:不需要,因为加载器应该用于加载模块,并且不推荐使用 find_module()。

and impmodule documentation recommends to use importlib:

imp模块文档建议使用importlib

NoteNew programs should use importlib rather than this module.

注意新程序应该使用 importlib 而不是这个模块。

What is the proper way to load an arbitrary python source file in Python 3.3+ without using the deprecated imp.load_modulefunction?

在不使用弃用imp.load_module函数的情况下,在 Python 3.3+ 中加载任意 Python 源文件的正确方法是什么?

采纳答案by falsetru

Found a solution from importlibtest code.

importlib测试代码中找到了解决方案。

Using importlib.machinery.SourceFileLoader:

使用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'>

NOTE: only works in Python 3.3+.

注意:仅适用于Python 3.3+

UPDATELoader.load_moduleis deprecated since Python 3.4. Use Loader.exec_moduleinstead:

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'>


>>> 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'>

回答by Stefan Scherfke

Shorter version of @falsetru 's solution:

@falsetru 解决方案的较短版本:

>>> 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'>

I tested it with Python 3.5 and 3.6.

我用 Python 3.5 和 3.6 对其进行了测试。

According to the comments, it does not work with arbitrary file extensions.

根据评论,它不适用于任意文件扩展名。

回答by Alex Walczak

Similar to @falsetru but for Python 3.5+and accounting for what the importlibdocstates on using importlib.util.module_from_specover types.ModuleType:

类似@falsetru但对于Python的3.5+和占什么样importlib文档使用状态importlib.util.module_from_spectypes.ModuleType

This function [importlib.util.module_from_spec] is preferred over using types.ModuleTypeto create a new module as spec is used to set as many import-controlled attributes on the module as possible.

此函数 [ importlib.util.module_from_spec] 优于types.ModuleType用于创建新模块,因为规范用于在模块上设置尽可能多的导入控制属性。

We are able to import any file with importlibalone by modifying the importlib.machinery.SOURCE_SUFFIXESlist.

我们可以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()