我需要发送 集合 的 Python 程序,这些程序使用存储在本地 Library
中的多个包目录:目标是避免用户在使用我的程序之前安装包(包在 Library
目录中提供)。导入 Library
中包含的包的最佳方式是什么? ?
我尝试了三种方法,但没有一种看起来是完美的:是否有更简单、更可靠的方法?还是这些方法中的一种是最好的方法?
在第一种方法中,
Library
文件夹只是添加到库路径:import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library')) import package_from_Library
Library
文件夹放在开头,这样我的程序随附的软件包优先于用户安装的相同模块(这样我可以确保它们具有正确的版本来与我的程序一起使用)。此方法在Library
时也有效。文件夹不在当前目录中,这很好。然而,这种方法有缺点。我的每个程序都将相同路径的副本添加到sys.path
,这是一种浪费。此外,所有程序都必须包含相同的三行路径修改行,这违反了不要重复自己的原则。对上述问题的改进在于尝试添加
Library
路径只有一次,通过在导入的模块中执行:# In module add_Library_path: sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library'))
然后在我的每个程序中使用:
import add_Library_path import package_from_Library
这样,得益于CPython的缓存机制,模块
add_Library_path
只运行一次,Library
路径仅添加一次到sys.path
.然而,这种方法的缺点是import add_Library_path
有一个看不见的副作用,导入的顺序很重要:这使代码更难读,更脆弱。此外,这迫使我的程序分发包含一个add_Library_path.py
。用户不会使用的程序。Python 模块 来自
Library
也可以通过将其打包(内部存储空__init__.py
文件)来导入,这样可以执行以下操作:from Library import module_from_Library
但是,这会中断
Library
中的包 ,因为他们可能会做类似from xlutils.filter import …
的事情,因为xlutils
而中断未在sys.path
中找到.因此,此方法有效,但仅当在Library
中包含模块时有效。 ,不是包。
所有这些方法都有一些缺点。
有没有更好的方法来运送程序,其中包含存储在本地 Library
中的一组包(他们使用)目录?还是上述方法之一(方法 1?)是最好的方法?
PS:在我的例子中,来自 Library
的所有包裹是纯 Python 包,但适用于任何操作系统的更通用的解决方案是最好的。
PPS:目标是用户无需安装任何东西(除了复制我定期发布的目录)即可使用我的程序,如上例所示。
PPPS:更准确地说,目标是能够灵活地更新我的程序集及其来自 Library
的相关第三方程序包。通过让我的用户对包含我的程序和 Library
的目录进行简单复制 “隐藏”第三方包的文件夹。 (我经常更新,所以我不想强制用户也更新他们的 Python 发行版。)
最佳答案
乱用 sys.path()
会导致痛苦... modern package template和 Distribute包含大量信息,部分设置是为了解决您的问题。
我要做的是设置 setup.py 以将所有包安装到特定的站点包位置,或者如果您可以将其安装到系统的站点包。在前一种情况下,本地站点包将被添加到系统/用户的 PYTHONPATH 中。在后一种情况下,无需更改任何内容
您也可以使用批处理文件来设置 python 路径。或者更改 python 可执行文件以指向包含修改后的 PYTHONPATH 的 shell 脚本,然后执行 python 解释器。当然,后者意味着您必须有权访问用户的机器,而您没有。但是,如果您的用户只运行脚本而不导入您自己的库,您可以使用您自己的脚本包装器:
#!/path/to/my/python
/path/to/my/python
脚本应该是这样的:
#!/bin/sh
PYTHONPATH=/whatever/lib/path:$PYTHONPATH /usr/bin/python $*
关于python - Python包的本地集合: best way to import them?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15026634/