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