Python导入,包和运行的脚本
我读过下面的帖子:Python导入,包和运行的脚本
Relative imports for the billionth time
它说明了运行的文件作为顶级脚本和导入它作为显着模块之间的区别清晰度和细节。
但是我不知道如何编写一个可运行脚本(if __name__ == '__main__'
等等)的导入方式,我也可以从我的测试中导入它,同时保持可运行的状态脚本独立(即不需要安装包)。
说我有以下项目层次:
/reporoot
/mypkg
/mysubpkg
__init__.py
subpkgmodule.py
__init__.py
main1.py
main2.py
/tests
test_main1.py
test_main2.py
test_main1
需要以某种方式导入main1
,并且main1
需要以某种方式导入subpkgmodule
。 如果,例如,main1
进口subpkgmodule
像这样:
import mysubpkg.subpkgmodule
这将运行该脚本的顶层脚本时,因为顶层脚本有其目录添加到sys.path
做工精细。但是,导入模块时导入会中断,因为它的目录不会被添加到sys.path
。
如果main1
是进口subpkgmodule
像这样:
import mypkg.mysubpkg.subpkgmodule
当包是一个安装包(包括python setup.py develop
),而不是运行作为一个独立的脚本,这只会工作(即不干了一些文件系统,运行python main1.py
)。
我看到标准库的http.server
模块有一个import http.client
,因此不能像我提到的那样作为独立脚本运行。
对于我的可运行脚本的导入,干净的解决方案是什么?
典型的方法是将sys.path
放在可运行的脚本中,并将其放在包中。
指定模块搜索路径的字符串列表。 从环境变量PYTHONPATH初始化,再加上一个依赖于安装的默认值 。
在程序启动时初始化,此列表中的第一项 path [0]是包含用于调用Python解释器的脚本的目录。如果脚本目录不是 可用(例如,如果解释器是交互式调用的,或者 脚本是从标准输入读取的),则path [0]是空字符串, 指示Python首先搜索当前目录中的模块。 请注意,在作为PYTHONPATH的结果插入条目 之前插入了脚本目录。
程序可以根据自己的目的自由修改此列表。
样品test_main1.py
:
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir))
import mypkg.mysubpkg.subpkgmodule # should import fine
if __name__ == "__main__":
pass # runnable code here
库,如内置unittest
有内置的测试发现。默认情况下,它希望测试位于以test*.py
模式命名的文件中,其中星号(*)可以是任何您想要的。然后,您会使用discover
和使用运行包:
python -m unittest discover
这假定
- 您使用
unittest
, - 你的测试子类
unittest.TestCase
和 - 您使用默认类
unittest.TestLoader
。
我曾经想过通过一些'testenv'模块来做这件事,所有的测试都会先导入,但看起来不够好看 – DoomMuffins