【问题标题】:Detect python package installation path from within setup.py从 setup.py 中检测 python 包安装路径
【发布时间】:2023-03-14 22:51:01
【问题描述】:

安装后,我想对安装创建的一些配置和数据文件进行软链接。

如何确定从包的 setup.py 中安装的新包文件的位置?

我最初对路径“/usr/local/lib/python2.7/dist-packages”进行了硬编码,但是当我尝试使用虚拟环境时,它就坏了。 (由 virtualenv 创建。)

我尝试了 distutils.sysconfig.get_python_lib(),它在 virtualenv 中工作。但是,当安装在真实系统上时,它会返回“/usr/lib/python2.7/dist-packages”(注意“本地”目录不存在。)

我也试过 site.getsitepackages():

从基础环境运行 Python shell:

导入网站

site.getusersitepackages()

'/home/sarah/.local/lib/python2.7/site-packages'

site.getsitepackages()

['/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages']

从虚拟环境“testenv”运行 Python shell:

导入网站

site.getsitepackages()

Traceback(最近一次通话最后一次):

文件“”,第 1 行,在

AttributeError: 'module' 对象没有属性 'getsitepackages'

我在 Ubuntu 上运行“Python 2.7.3(默认,2012 年 8 月 1 日,05:14:39)”和“Linux2 上的 [GCC 4.6.3]”。我可能可以用 try-except 块拼凑一些东西,但似乎应该有一些变量集 / 由 distutils / setuptools 返回。 (我不知道使用哪个分支,只要它有效。)

谢谢。

【问题讨论】:

  • 一种方法是到import <yourpackage> 并从<yourpackage>.__file__ 中删除包名称。不过我敢肯定还有更好的方法。
  • 我可能会尝试将其作为一种解决方法,但我希望得到一些不会让人感觉像拼凑的东西。在相关说明中, setuptools.setup() 返回一个对象,但它似乎没有描述它所做的属性。 build/、dist/ 和 *.egg-info/ 目录是似乎适合此信息的附加位置......但他们没有。
  • 在 distutils 的源代码中寻找一些有趣的项目:distutils.command.install.INSTALL_SCHEMES distutils.command.install.install.user_options distutils.command.install.install.sub_commands 看起来像他们有相关信息/功能,但我还不知道如何利用它们......尤其是在 setup.py 中

标签: python path installation setup.py


【解决方案1】:

我还没有找到这样做的“正确”方法,但我发现了一些看起来几乎正确的技巧。一种方法仅适用于安装;另一个仅在已安装软件包时才有效。

对于安装,我使用setuptools.setup()返回的对象:

from setuptools import setup
s = setup([...])
installation_path = s.command_obj['install'].install_lib

(这仅在安装期间有效,因为您需要一个有效的 Distribution 对象才能使这些属性存在。AFAIK,获取此类对象的唯一方法是运行 setup()。)

卸载时,我使用包的 file 属性,正如上面@Zhenya 所建议的那样。唯一的问题是,当我运行./setup.py uninstall 以摆脱package 时,我通常有目录./package/./build./dist./package.egg-info/。 (“卸载”选项被我的代码捕获,而无需调用 setup()。它运行手动创建的脚本来删除包文件。)这些可以将 python 解释器重定向到我所在的全局可访问存储库之外的某个地方试图摆脱。这是我的处理方法:

import imp
import sys
from subprocess import Popen
from os import getcwd
Popen('rm -r build dist *.egg-info', shell=True).wait()
oldpath = sys.path
rundir = getcwd()
sys.path.remove(rundir)
mod = imp.find_module(PACKAGE)
p = imp.load_module(PACKAGE, mod[0], mod[1], mod[2])
sys.path = oldpath
installation_path = p.__file__

(这在安装过程中不起作用,因为 - 我认为 - Python 在启动时只对模块进行清单,所以 find_module() 不会找到刚刚安装的包,除非你退出 python 并重新进入。)

我已经在裸环境和虚拟环境(从 virtualenv 1.9.1 开始)上测试了安装和卸载。我正在运行 Ubuntu 12.04 LTS、Python 2.7.3、setuptools 0.6c11(在裸环境中)和 setuptools 0.7.4(在 virtualenv 中)。

【讨论】:

  • 我想这不再起作用了。在 Python 3 中,我得到 Traceback(最近一次调用最后):文件“”,第 1 行,在 文件“/tmp/pip-req-build-a1c6n4hb/setup.py”,第 14 行,在 s = setup([...]) TypeError: setup() 接受 0 个位置参数,但给出了 1 个
  • 这在 Python 3 中可能不起作用,但您收到的错误消息表明您省略了 setup() 所需的输入。 (我将它们排除在我的答案之外,因为它们是特定于环境的。)请参阅setuptools.readthedocs.io/en/latest/… 的 Python 3 setup() 详细信息
  • 啊,是的,对不起,我太笨了。但是,我有两个问题:1.我需要知道安装路径在运行setup()之前,因为我必须在setup中告诉一些额外的构建代码关于这个路径,所以它可以设置类似的东西rpaths 并将文件复制到正确的位置。 2. 我试图通过在我的真实对象之前创建一个“虚拟”setup() 对象来规避这个问题,但它什么也没做,但是我还是得到了错误:KeyError:'install'。所以也许它在 Python 3 中无论如何都不起作用。
  • 为此,我会尝试手动挖掘 setup() 的代码(和文档),寻找系统如何确定适当的路径...根据我的经验,路径似乎已确定基于系统参数、setup.py 调用的详细信息(如用户权限)和 Python 版本,与正在安装的包几乎没有关系(没有关系?)。由于您可以控制调用 setup.py 的脚本,因此您可以尝试测试安装并假设它始终是相同的路径。
【解决方案2】:

这可能无法回答您的问题,但如果您需要访问已安装的软件包的源代码或此软件包中的任何其他文件,最好的方法是在开发模式下安装此软件包(通过下载源代码,将其放在您想要的任何位置,然后在包源代码的基本目录中运行 python setup.py develop)。这样你就知道包在哪里了。

【讨论】:

  • 这是我以前从未见过的一个有趣的功能(谢谢!),但它似乎并不能帮助我在其他地方建立到代码的链接。
猜你喜欢
  • 2011-05-23
  • 2021-12-08
  • 1970-01-01
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
相关资源
最近更新 更多