在运行setuptools测试时访问包的`__init__.py`中定义的名称
我开始把模块代码直接放在包的 __init__.py
文件里,即使是一些简单的包,这样做之后,这个包就成了唯一的文件。
所以我有一堆包看起来像这样(虽然它们不都是叫 pants
:))
+ pants/
\-- __init__.py
\-- setup.py
\-- README.txt
\--+ test/
\-- __init__.py
我之所以这样做,是因为这样可以把代码放在一个单独的(而且可以单独管理版本的)目录里,并且它的工作方式和如果包放在一个单独的 module.py
文件里是一样的。我把这些包放在我的开发 Python 库目录里,并在做这些事情时把它添加到 $PYTHONPATH
中。每个包都是一个独立的 git 仓库。
编辑...
与典型的 Python 包结构相比,比如 Radomir 的 回答 中所示,这种设置让我不需要把每个包的目录都添加到我的 PYTHONPATH 中。
.../编辑
这方法效果不错,但我遇到了一个(有点晦涩的)问题:
当我在包目录中运行测试时,包本身,也就是 __init__.py
中的代码,并不一定会在 sys.path
中。这在我通常的环境下不是问题,但如果有人下载了 pants-4.6.tgz
并解压了源代码包,进入目录后运行 python setup.py test
,那么包 pants
通常不会在他们的 sys.path
中。
我觉得这很奇怪,因为我本以为 setuptools
会从被测试包的父目录运行测试。但不知为何,它并没有这样做,我猜是因为通常不会以这种方式打包。
相对导入不工作,因为 test
是一个顶级包,它是作为当前目录的子目录出现在 sys.path
中的。
我希望避免把代码移到一个单独的文件中,并在 __init__.py
中导入它的公共名称。主要是因为这样做看起来对一个简单模块来说是多余的。
我可以在 setup.py
中明确地将父目录添加到 sys.path
,但我不太想这样做。首先,这在理论上可能会失败,比如如果有人决定从他们的文件系统根目录(大概是 Windows 驱动器)运行测试。但主要是这感觉有点不靠谱。
有没有更好的方法?
把代码放在 __init__.py
中被认为特别不妥吗?
1 个回答
我觉得打包Python程序的标准方式应该是这样的:
\-- setup.py
\-- README.txt
\--+ pants/
\-- __init__.py
\-- __main__.py
...
\--+ tests/
\-- __init__.py
...
\--+ some_dependency_you_need/
...
这样你就可以避免这个问题了。