我正在编写两个旨在从命令行运行的脚本。我们称他们为foo.py
和bar.py
。另外,我有一个名为util
的实用程序模块,它将由这两个脚本共享。如何构建代码,以便foo
和bar
都可以使用import util
之类的简单行?目前,我的目录结构如下:
MyProject
\--foo
\--foo.py
\--foo_util.py
\--bar
\--bar.py
\--bar_util.py
\--util
\--util.py
在foo
内,我希望能够写import foo_util
和import util
,但我不会这样做。希望能够写import bar
,因为它们是独立的程序,没有理由彼此使用'代码。
更新:chepner解决方案的略微修改版本,我发现了一些似乎对我有用的东西。我的项目现在结构如下:
MyProject
\--__init__.py
\--foo.py
\--bar.py
\--MyProject
\--__init__.py
\--foo
\--__init__.py
\--foo_impl.py
\--bar
\--__init__.py
\--bar_impl.py
\--shared
\--__init__.py
\--util.py
foo.py
可以写import MyProject.foo as foo
而bar.py
可以做类似的事情,而foo
和bar
都可以import MyProject.shared
答案 0 :(得分:3)
我建议采用以下布局:foo.py
和bar.py
作为脚本,可以放在任何地方。您应该在已知位置安装以下包:
<known location, such as /usr/lib/python/site-packages>
\--foo
\--util.py
\--bar
\--util.py
\--util.py
然后,使用import foo.util
,import bar.util
和import util
在必要的时间和地点访问各个模块。
正如abarnert指出的那样,你无法隐藏bar/util.py
foo
,也不关心这样做。
答案 1 :(得分:0)
将util
放入site-packages
。这就是你希望能够import
进入多个项目的任何模块应该去的地方。
答案 2 :(得分:0)
import util
,根据您当前的结构,不会导入您的util:它导入Python的util模块。要解决这个问题,你必须将__init__.py添加到util目录,这使它成为有效的Python包。
为了导入你的util,你可以做相对导入(这会违反你的第二个愿望,甚至要求你的应用程序成为一个包)或使用PYTHONPATH
来运行你的脚本。
PYTHONPATH="../util" python foo.py
如果您想将util用作库,它属于site-packages
目录,隐含位于PYTHONPATH
。
答案 3 :(得分:0)
我认为你在这里缺少的是构建一个可安装的基于setuptools
的软件包解决了你的问题,而实际上并没有要求你在系统范围内安装任何东西。
首先,这种事情正是为virtualenv
创建的。 (或者,如果您使用的是3.4+,那么stdlib的venv
。)您可以创建一个新的虚拟环境。在该环境中,您pip install .
是util
库,现在它位于该环境的site-packages
中。然后,您可以在该环境中运行foo
和bar
以及其他任何内容,并且它们都可以import util
- 但您的主系统环境中没有任何变化。
即使您出于某种原因不想使用virtualenv
(但您确实应该......),如果您正确构建设置,它将允许您以“开发”模式运行所有内容,伪造安装到源树下的目录,并设置所有链接以使其工作。当您尝试安装多个单独的脚本以及它们共享的模块时,这可能有点繁琐,但它确实有效。
关于如何布局分布的完整教程,让setuptools
自动生成包装器脚本并将它们安装到bin
等等,对于这里的答案来说太大了,PyPA人{ {3}}。有一些复杂的部分,所以你可能会在某些时候陷入困境,但是当你这样做时,你会有另一个好问题要问SO。 :)