部署一个带有共享包的Python应用程序

2 投票
4 回答
1270 浏览
提问于 2025-04-11 19:09

我在考虑如何安排一个已经部署的Python应用程序,它将包含:

  1. 一个位于/usr/bin/的可执行脚本,这个脚本会提供命令行接口(CLI),让用户可以使用程序的功能。
  2. 一个库,这个库会安装到当前的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/READMETwisted/setup.py 来解释和安装你的软件。

不要:

  • 把源代码放在叫 srclib 的目录里。这样会让运行变得困难。
  • 把测试放在Python包外面。这样会让测试很难与已安装的版本一起运行。
  • 创建一个只有 __init__.py 的包,然后把所有代码放在 __init__.py 里。直接做一个模块就好了,这样更简单。
  • 试图想出一些神奇的技巧,让Python能在用户不把包含模块或包的目录添加到导入路径(比如 PYTHONPATH 或其他方式)的情况下导入你的模块或包。这样你可能无法正确处理所有情况,用户会因为你的软件在他们的环境中无法工作而生气。

撰写回答