导入不带.py扩展名的python模块
我有一个名为foobar的文件(没有.py扩展名)。在同一目录中,我有另一个python文件试图导入它:导入不带.py扩展名的python模块,python,import,Python,Import,我有一个名为foobar的文件(没有.py扩展名)。在同一目录中,我有另一个python文件试图导入它: import foobar 但是,只有将文件重命名为foobar.py时,这才有效。是否可以导入没有.py扩展名的python模块 更新:该文件没有扩展名,因为我也将其用作独立脚本,并且我不想键入.py扩展名来运行它 更新2:我将使用下面提到的符号链接解决方案。您可以使用imp.load\u source函数(从imp模块)从给定的文件系统路径动态加载模块 import imp fooba
import foobar
但是,只有将文件重命名为foobar.py时,这才有效。是否可以导入没有.py扩展名的python模块
更新:该文件没有扩展名,因为我也将其用作独立脚本,并且我不想键入.py扩展名来运行它
更新2:我将使用下面提到的符号链接解决方案。您可以使用
imp.load\u source
函数(从imp
模块)从给定的文件系统路径动态加载模块
import imp
foobar = imp.load_source('foobar', '/path/to/foobar')
这还显示了一些有趣的选项。
imp.load\u源代码(模块名称、路径)
应该做,或者您可以做更详细的imp.load\u模块(模块名称、文件句柄等)
路由如果您有一个文件句柄,而不是像其他人提到的那样,您可以使用imp.load\u源代码,但这会使您的代码更难阅读。只有当您需要导入在运行时之前名称或路径未知的模块时,我才真正推荐它
您不想使用.py扩展名的原因是什么?不希望使用.py扩展的最常见情况是,python脚本也作为可执行文件运行,但您仍然希望其他模块能够导入它。如果是这种情况,将功能移动到具有类似名称的.py文件中,然后使用
foobar
作为包装器可能会有所帮助。如果使用软件包管理器(deb或类似工具)安装脚本,另一个选项是使用setuptools:
“…要使脚本的文件名与Windows和POSIX平台上的本地约定相匹配并不容易。另一方面,当实际的“主”脚本是某个模块中的函数…setuptools通过自动为您生成具有正确扩展名的脚本修复了所有这些问题,在Windows上它甚至会创建一个.exe文件
以下是Python 3.4+的解决方案:
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
spec = spec_from_loader("foobar", SourceFileLoader("foobar", "/path/to/foobar"))
foobar = module_from_spec(spec)
spec.loader.exec_module(foobar)
使用并显式指定将强制将文件作为源加载,而不尝试从扩展名中找出文件的类型。这意味着您可以加载该文件,即使该文件未在中列出
如果要在首次加载后按名称继续导入文件,请将模块添加到sys.modules
:
sys.modules['foobar'] = foobar
importlib
helper函数
下面是一个方便的、随时可用的帮助程序,用于替换imp
,并提供了一个示例,该示例基于以下内容:
main.py
#!/usr/bin/env python3
import os
import importlib
import sys
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)
非主要
x = 1
运行:
输出:
<module 'not_main' from 'not-main'>
1
我不知道如何关闭它,有人问:
在Python 3.7.3中进行了测试。我尝试了上面的所有建议,但对于一个非常简单的情况,我无法找到解决方案,即我要对没有
.py
扩展名的cli脚本进行pytest
为什么spec.loader.exec_module()
会在“
”上引发IsADirectoryError
我在一个目录中有两个文件:
%ls
cli_with_no_dot_py test_cli_with_no_dot_py.py
%cat cli\u,不带点\u py
#!/usr/bin/env python3
cool_thing = True
print("cool_thing is", cool_thing)
cool_thing is True
%/cli\u带\u no\u dot\u py
#!/usr/bin/env python3
cool_thing = True
print("cool_thing is", cool_thing)
cool_thing is True
%cat test\u cli\u带\u no\u dot\u py.py
#!/usr/bin/env python3
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
spec = spec_from_loader("cli_with_no_dot_py",
SourceFileLoader("cli_with_no_dot_py", "."))
print("spec:", spec)
cli_with_no_dot_py = module_from_spec(spec)
print("cli_with_no_dot_py):", cli_with_no_dot_py)
print("dir(cli_with_no_dot_py:", dir(cli_with_no_dot_py))
print("spec.loader:", spec.loader)
spec.loader.exec_module(cli_with_no_dot_py) # !!! IsADirectoryError !!!
def test_cool_thing():
print("cli_with_no_dot_py.cool_thing is", cli_with_no_dot_py.cool_thing)
assert cli_with_no_dot_py.cool_thing
%pytest
======================================================================== test session starts ========================================================================
platform darwin -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /Users/cclauss/Python/pytest_a_cli_tool
collected 0 items / 1 error
============================================================================== ERRORS ===============================================================================
____________________________________________________________ ERROR collecting test_cli_with_no_dot_py.py ____________________________________________________________
test_cli_with_no_dot_py.py:11: in <module>
spec.loader.exec_module(cli_with_no_dot_py)
<frozen importlib._bootstrap_external>:779: in exec_module
???
<frozen importlib._bootstrap_external>:915: in get_code
???
<frozen importlib._bootstrap_external>:972: in get_data
???
E IsADirectoryError: [Errno 21] Is a directory: '.'
-------------------------------------------------------------------------- Captured stdout --------------------------------------------------------------------------
spec: ModuleSpec(name='cli_with_no_dot_py', loader=<_frozen_importlib_external.SourceFileLoader object at 0x10e106f70>, origin='.')
cli_with_no_dot_py: <module 'cli_with_no_dot_py' from '.'>
dir(cli_with_no_dot_py): ['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
spec.loader: <_frozen_importlib_external.SourceFileLoader object at 0x10e106f70>
====================================================================== short test summary info ======================================================================
ERROR test_cli_with_no_dot_py.py - IsADirectoryError: [Errno 21] Is a directory: '.'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================================= 1 error in 0.09s ==========================================================================
==========================================================================================================================================测试会话开始========================================================================
平台darwin——Python 3.8.2、pytest-5.4.1、py-1.8.1、Plugy-0.13.1
rootdir:/Users/cclauss/Python/pytest\u a\u cli\u工具
已收集0个项目/1个错误
==============================================================================================================================错误===============================================================================
____________________________________________________________使用\u no\u dot\u py.py收集测试\u cli\u时出错____________________________________________________________
测试带有点的客户端。点:11:in
spec.loader.exec_模块(cli_,不带点)
:779:in exec_模块
???
:915:输入get_代码
???
:972:输入获取数据
???
E isDirectoryError:[Errno 21]是一个目录:'
--------------------------------------------------------------------------俘获stdout--------------------------------------------------------------------------
规格:ModuleSpec(name='cli',带有'u no'u dot'u py',loader=,origin='。)
不带点的客户端:
目录(不带点的cli):[“文档”、“文件”、“加载程序”、“名称”、“包”、“规范”]
规格装载机:
======================================================================================================================================================简短测试摘要信息======================================================================
错误测试\u cli\u带有\u no\u dot\u py.py-isDirectoryError:[Errno 21]是一个目录:'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 中断:收集过程中出现1个错误!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
===============================================================================================================================0.09s内出现1个错误==========================================================================
我很感兴趣。为什么python文件没有扩展名py
呢?有时候,将python用于配置文件(扩展名为.conf)或表示一种特殊类型的文件是不错的选择。在我的例子中,这对管理员来说更方便。我有一个配置为python文件和bash脚本的文件。我给了它一个pysh
扩展…如果这是与配置相关的东西,我建议使用ConfigParser
@voyager的一个原因是python脚本带有.cgi扩展名而不是.py扩展名,或者不用包装,只需将foobar.py符号链接到foobar(假设您不在Windows上)@whaley,是的,这会更干净。你可以使用.bat for windows来完成同样的事情。我有一个