我在单个文件app_name.py
中编写了一个命令行应用程序,但它确实有效。现在我将它分解为不同的.py文件,以便于管理和可读性。我将所有这些py文件放在src/
文件夹中,因为我在github上看到了很多。
app_name/
src/
file1.py
file2.py
cli.py
__init__.py
我已将所有导入放入__init__.py
from .file1 import function1
中的相对导入不在__init__
中,并且放在需要的单个文件中。例如,
#!usr/bin/env python
#__init__.py
import os
import argparse
#etc...
run_cli()
在cli.py中,我有
from .file1 import function1
def run_cli(): pass
if __name__ == '__main__':
run_cli()
这是因为当我使用时,在实际的命令行app_name <arguments>
上,__name__
不是主要的,所以我在run_cli()
中呼叫__init__.py
。虽然这看起来并不正确,但我必须致电src
而不是app_name
答案 0 :(得分:2)
我认为你可能会混淆两件事。在您的源代码发布中有一个src
目录是一个相当普遍,惯用的事情;在已安装的软件包或应用程序中使用它,而不是那么多。
有两种基本方法可以解决这个问题。
首先,您可以构建一个Python程序包,将程序包安装到site-packages中,并将脚本安装到Python脚本在PATH上的任何位置。 Python Packaging User Guide在其构建和分发包的教程中介绍了这一点。请参阅Layout和Scripts部分以及从那里链接的示例。
这通常会为您提供如下安装的布局:
<...somewhere system/user/venv .../lib/pythonX.Y/site-packages>
app_name/
file1.py
file2.py
cli.py
__init__.py
<...somewhere.../bin/>
app_name
但是,根据用户选择安装东西的方式,它可能是鸡蛋,拉链包装,轮子或其他任何东西。只要您的代码有效,您就不在乎了。特别是,您的代码可以假设app_name
是可导入的包。
理想情况下,路径上的app_name
脚本是一个“入口点”脚本(pip
本身可能是您系统上的一个很好的示例),理想情况下是在安装时即时构建的脚本。使用setuptools
,您可以指定它应该导入哪个包以及它应该在该包中调用哪个函数,它将执行其他所有操作 - 确保在安装时实际使用Python,找出如何{{ 1}}将软件包添加到pkg_resources
(默认情况下不需要,但如果您不希望它是可导入的,则可以使其工作),依此类推。
如原始提问者的评论中所述,python-commandline-bootstrap可能会帮助您更快地将此解决方案整合在一起。
另一种方法是将所有内容保留在网站包之外,并使包特定于您的应用。在这种情况下,您基本上想要做的是:
sys.path
之前将dirname(abspath(argv[0]))
添加到sys.path
。import
上的某个位置。在这种情况下,你必须手动编写包装脚本,但是你不需要任何花哨的东西。
但是,通常,您并不希望应用程序依赖于具有某些特定版本和Python设置的用户。您可能希望使用PATH
,pyInstaller
,py2exe
,py2app
,cx_Freeze
等工具来执行上述所有操作。他们都做了不同的事情,一直到构建Mac zc.buildout
捆绑目录的极端,使用自定义的,独立的,剥离的Python框架和stdlib以及嵌入框架的包装器可执行文件。
无论哪种方式,您真的不想调用包目录.app
。这意味着包本身将被命名为src
,这不是一个好名字。如果您的应用被称为src
,您希望在追溯中看到spamifier
,而不是spamifier
,对吧?