部署一个带有共享包的Python应用程序
我在考虑如何安排一个已经部署的Python应用程序,它将包含:
- 一个位于/usr/bin/的可执行脚本,这个脚本会提供命令行接口(CLI),让用户可以使用程序的功能。
- 一个库,这个库会安装到当前的site-packages目录下。
现在,我的源代码目录结构是这样的:
foo.py
foo/
__init__.py
...
我觉得这样做可能不是最好的方式。在开发过程中,一切都按预期工作,但在部署后,foo.py中的“from foo import FooObject”这行代码似乎试图导入它自己,这不是我想要的效果。
所以,我想问一下,像这种情况的标准做法是什么?我想到的一种方法是,在安装时把foo.py重命名为foo,这样就不会导入它自己了,但这样似乎有点尴尬……
我想问题的另一部分是命名上的挑战。也许可以把可执行脚本叫做foo-bin.py?
4 个回答
0
你的命令行界面模块和支持它的包是两回事。不要把模块 foo
(在文件 foo.py
中)和包 foo
(在一个名为 foo
的文件夹里,里面有一个 __init__.py
文件)搞混了。
你有两个东西都叫 foo
:一个是模块,一个是包。你还想把 foo
叫成什么呢?一个类?一个函数?还是一个变量?
给 foo 模块或 foo 包起个独特的名字吧。比如,foolib
就是一个很受欢迎的包名。
2
Distutils 是一个工具,可以帮助你安装模块、包和脚本。如果你创建一个叫做 setup.py
的文件,并在里面把 foo
指定为一个包,把 foo.py
指定为一个脚本,那么 foo.py
会被安装到 /usr/local/bin
这个地方,或者根据你使用的操作系统,安装到合适的脚本路径。而 foo
这个包则会被安装到 site_packages
目录里。
5
这篇文章写得不错,给你提供了一个很好的做法。做列表中的第二条正好回答了你的问题。
不怕抄袭:
Python项目的文件结构
作者:Jp Calderone
做:
- 给你的项目目录起个相关的名字。比如,如果你的项目叫“Twisted”,那么顶层目录就叫
Twisted
。发布版本时,最好加上版本号,比如Twisted-2.5
。- 创建一个目录
Twisted/bin
,把你的可执行文件放在这里。如果有可执行文件,不要给它们加.py
后缀,即使它们是Python源文件。这里面只放一个导入和调用其他地方定义的主函数的代码。- 如果你的项目可以用一个Python源文件表达,那就把它放到这个目录里,起个相关的名字。比如
Twisted/twisted.py
。如果需要多个源文件,就创建一个包(Twisted/twisted/
,并在里面放一个空的Twisted/twisted/__init__.py
),把源文件放进去。比如Twisted/twisted/internet.py
。- 把你的单元测试放在包的子包里(注意,这意味着上面提到的单个Python源文件的选项是个小把戏——你总是需要至少一个其他文件来放单元测试)。比如
Twisted/twisted/test/
。当然,要把它做成一个包,里面要有Twisted/twisted/test/__init__.py
。测试文件可以命名为Twisted/twisted/test/test_internet.py
。- 如果你愿意,可以添加
Twisted/README
和Twisted/setup.py
来解释和安装你的软件。不要:
- 把源代码放在叫
src
或lib
的目录里。这样会让运行变得困难。- 把测试放在Python包外面。这样会让测试很难与已安装的版本一起运行。
- 创建一个只有
__init__.py
的包,然后把所有代码放在__init__.py
里。直接做一个模块就好了,这样更简单。- 试图想出一些神奇的技巧,让Python能在用户不把包含模块或包的目录添加到导入路径(比如
PYTHONPATH
或其他方式)的情况下导入你的模块或包。这样你可能无法正确处理所有情况,用户会因为你的软件在他们的环境中无法工作而生气。