【问题标题】:How to get installation directory using setuptools and pkg_ressources如何使用 setuptools 和 pkg_ressources 获取安装目录
【发布时间】:2016-07-11 06:44:14
【问题描述】:

我正在使用 setuptools 和 pkg_resources 开发一个包 P, 安装包后,需要下载一些二进制文件并将它们放在专用目录中(P/bin/)。

我正在尝试使用pkg_ressources.resource_filename 来获取绝对目录路径。 (为了使用 virtualenv)

在使用python setup.py install 安装期间,pkg_ressources.resource_filename 不会返回 /home/user/tests/venv/lib/python3.4/site-package/P/bin/ 之类的路径,但实际模块的路径,例如 /home/user/projects/P/P/bin/

这是个问题,因为我需要安装目录(在 virtualenv 中),而不是我的个人项目目录(我开发模块的地方)。

如果我尝试通过 pypi,使用 pip install modulepkg_ressources.resource_filename 返回的目录是像 /tmp/pip-build-xxxxxxx/P/bin/ 这样的临时文件,这又不是放置二进制文件的地方。

这是我的 setup.py:

from setuptools import setup
import os

from setuptools.command.install import install as _install
from pkg_resources import resource_filename


def post_install():
    """Get the binaries online, and give them the execution permission"""
    package_dir_bin = resource_filename('P', 'bin') # should be /home/user/tests/venv/lib/python3.4/site-package/P/bin/
    # package_dir_bin = resource_filename(Requirement.parse('P'), 'bin') # leads to same results
    put_binaries_in(package_dir_bin)
    os.system('chmod +x ' + package_dir_bin + '*')



class install(_install):
    # see http://stackoverflow.com/a/18159969

    def run(self):
        """Call superclass run method, then downloads the binaries"""
        _install.run(self)
        self.execute(post_install, args=[], msg=post_install.__doc__)


setup(
    cmdclass={'install': install},
    name = 'P',
    # many metadata
    package_dir = { 'P' : 'P'},
    package_data = {
        'P' : ['bin/*.txt'] # there is an empty txt file in bin directory
    },
)

安装过程中是否有标准的方式获取安装目录,跨平台兼容python 2和3? 如果没有,我该怎么办?

【问题讨论】:

    标签: python setuptools packaging pkg-resources


    【解决方案1】:

    一种解决方法是使用site 包而不是pkg_resources,它似乎不是为在安装期间访问资源而设计的。

    这是一个在安装过程中检测安装目录的函数:

    import os, sys, site
    
    def binaries_directory():
        """Return the installation directory, or None"""
        if '--user' in sys.argv:
            paths = (site.getusersitepackages(),)
        else:
            py_version = '%s.%s' % (sys.version_info[0], sys.version_info[1])
            paths = (s % (py_version) for s in (
                sys.prefix + '/lib/python%s/dist-packages/',
                sys.prefix + '/lib/python%s/site-packages/',
                sys.prefix + '/local/lib/python%s/dist-packages/',
                sys.prefix + '/local/lib/python%s/site-packages/',
                '/Library/Python/%s/site-packages/',
            ))
    
        for path in paths:
            if os.path.exists(path):
                return path
        print('no installation path found', file=sys.stderr)
        return None
    

    这个解决方案不兼容 Python 2.7,在使用 virtualenv 安装的情况下,因为关于模块 siteknown bug。 (见相关SO

    【讨论】:

    • 我似乎得到了误报。我不知道为什么它们都存在,但我似乎同时拥有'/usr/lib/python%s/dist-packages/'和/usr/local/lib/python%s/dist-packages/'。我想自动定位后者,但是您的脚本首先找到前者,所以我得到了错误的路径。是否没有可靠的方法来找到 Python 本身实际使用的路径?这个函数似乎只是猜测和希望最好的结果。
    • workaround 的定义有很多,你建议的一种可能是:只是猜测并希望最好的结果。在您的情况下,您可能希望更改内部路径列表中的顺序,这显然取决于目标操作系统。
    • 是的,不幸的是,这对我的需求来说太狡猾了。我将求助于在运行时找到这些东西的解决方案。奇怪的是,无法以标准方式找到这些信息......
    【解决方案2】:

    最简单的解决方案是跟随this answer的第一个sn-p。

    基本上,您只需将setup 调用保存在一个变量中,然后查看它的属性。有几个方便的

    from setuptools import setup
    
    s = setup(
        # ...
    )
    
    print(s.command_obj['install'].__dir__())
    
    # [..., 'install_base', 'install_lib', 'install_script', ...]
    

    我展示的分别是/usr/usr/lib/pythonX.Y/site-packages/usr/bin。但还有其他可能有用的属性。这些都是绝对路径。

    【讨论】:

      猜你喜欢
      • 2014-09-04
      • 2012-12-30
      • 1970-01-01
      • 2010-09-20
      • 2016-05-05
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多