Python软件包的本地集合:导入它们的最佳方法? [英] Local collection of Python packages: best way to import them?

查看:240
本文介绍了Python软件包的本地集合:导入它们的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要运送使用多个 packages 存储在本地Library目录中的Python程序的 collection :目的是避免用户在使用前安装软件包我的程序(软件包位于Library目录中).导入Library中包含的软件包的最佳方法是什么?

I need to ship a collection of Python programs that use multiple packages stored in a local Library directory: the goal is to avoid having users install packages before using my programs (the packages are shipped in the Library directory). What is the best way of importing the packages contained in Library?

我尝试了三种方法,但是它们都不是完美的:有没有一种更简单,更可靠的方法?还是这些方法中最好的一种?

I tried three methods, but none of them appears perfect: is there a simpler and robust method? or is one of these methods the best one can do?

  1. 在第一种方法中,只需将Library文件夹添加到库路径:

  1. In the first method, the Library folder is simply added to the library path:

import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library'))

import package_from_Library

Library文件夹放在开头,以便与我的程序一起提供的软件包优先于用户安装的相同模块(这样,我确定它们具有与我的程序一起使用的正确版本).当Library文件夹不在当前目录中时,此方法也适用,这很好.但是,这种方法有缺点.我的每个程序都向sys.path添加相同路径的副本,这很浪费.此外,所有程序都必须包含相同的三个修改路径的行,这违反了不要重复自己"的原则.

The Library folder is put at the beginning so that the packages shipped with my programs have priority over the same modules installed by the user (this way I am sure that they have the correct version to work with my programs). This method also works when the Library folder is not in the current directory, which is good. However, this approach has drawbacks. Each and every one of my programs adds a copy of the same path to sys.path, which is a waste. In addition, all programs must contain the same three path-modifying lines, which goes against the Don't Repeat Yourself principle.

对上述问题的改进在于,尝试通过在导入的模块中添加Library路径一次来添加该路径:

An improvement over the above problems consists in trying to add the Library path only once, by doing it in an imported module:

# In module add_Library_path:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'Library'))

然后在我的每个程序中使用:

and then to use, in each of my programs:

import add_Library_path
import package_from_Library

这样,由于CPython的缓存机制,模块add_Library_path仅运行一次,并且Library路径仅添加到sys.path一次.但是,此方法的缺点是import add_Library_path具有看不见的副作用,并且导入顺序很重要:这使代码更不清晰,更易碎.另外,这迫使我分发程序以包含用户不会使用的add_Library_path.py程序.

This way, thanks to the caching mechanism of CPython, the module add_Library_path is only run once, and the Library path is added only once to sys.path. However, a drawback of this approach is that import add_Library_path has an invisible side effect, and that the order of the imports matters: this makes the code less legible, and more fragile. Also, this forces my distribution of programs to inlude an add_Library_path.py program that users will not use.

Python modules 打包成一个包(存储在其中的空__init__.py文件)导入该包,该包可以执行以下操作:

Python modules from Library can also be imported by making it a package (empty __init__.py file stored inside), which allows one to do:

from Library import module_from_Library

但是,这会破坏Library中的,因为它们可能会执行类似from xlutils.filter import …的操作,但由于在sys.path中找不到xlutils,所以会中断.因此,此方法有效,但仅当在Library中包含模块而不在包中包含模块时.

However, this breaks for packages in Library, as they might do something like from xlutils.filter import …, which breaks because xlutils is not found in sys.path. So, this method works, but only when including modules in Library, not packages.

所有这些方法都有一些缺点.

All these methods have some drawback.

是否有更好的方法来运送带有存储在本地Library目录中的软件包(它们使用的软件包)的程序?还是上述方法之一(方法1?)是最好的?

Is there a better way of shipping programs with a collection of packages (that they use) stored in a local Library directory? or is one of the methods above (method 1?) the best one can do?

PS :就我而言,Library中的所有软件包都是纯Python软件包,但是最好是适用于任何操作系统的更通用的解决方案.

PS: In my case, all the packages from Library are pure Python packages, but a more general solution that works for any operating system is best.

PPS :目标是使用户能够使用我的程序而不必安装任何东西(除了复制我定期发送的目录之外),就像上面的示例一样.

PPS: The goal is that the user be able to use my programs without having to install anything (beyond copying the directory I ship them regularly), like in the examples above.

PPPS :更准确的说,目标是具有以下灵活性:轻松地更新我的程序集和来自Library的相关第三方程序包我的用户对包含我的程序和隐藏"第三方程序包的Library文件夹的目录进行了简单复制. (我经常进行更新,所以我不想强迫用户也更新他们的Python发行版.)

PPPS: More precisely, the goal is to have the flexibility of easily updating both my collection of programs and their associated third-party packages from Library by having my users do a simple copy of a directory containing my programs and the Library folder of "hidden" third-party packages. (I do frequent updates, so I prefer not forcing the users to update their Python distribution too.)

推荐答案

sys.path()混在一起会导致痛苦... Distribute 包含大量一系列信息,并已部分解决您的问题.

Messing around with sys.path() leads to pain... The modern package template and Distribute contain a vast array of information and were in part set up to solve your problem.

我要做的是设置setup.py,将所有程序包安装到特定的站点程序包位置,或者将其安装到系统的站点程序包中.在前一种情况下,本地站点包将被添加到系统/用户的PYTHONPATH中.在后一种情况下,无需更改

What I would do is to set up setup.py to install all your packages to a specific site-packages location or if you could do it to the system's site-packages. In the former case, the local site-packages would then be added to the PYTHONPATH of the system/user. In the latter case, nothing needs to changes

您也可以使用批处理文件来设置python路径.或将python可执行文件更改为指向包含修改后的PYTHONPATH的shell脚本,然后执行python解释器.当然,后者意味着您必须有权访问用户的计算机,而您没有权限.但是,如果您的用户仅运行脚本而不导入自己的库,则可以使用自己的脚本包装器:

You could use the batch file to set the python path as well. Or change the python executable to point to a shell script that contains a modified PYTHONPATH and then executes the python interpreter. The latter of course, means that you have to have access to the user's machine, which you do not. However, if your users only run scripts and do not import your own libraries, you could use your own wrapper for scripts:

#!/path/to/my/python

/path/to/my/python脚本类似于:

#!/bin/sh
PYTHONPATH=/whatever/lib/path:$PYTHONPATH /usr/bin/python $*

这篇关于Python软件包的本地集合:导入它们的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆