【问题标题】:How to properly get console_scripts install_scripts directory?如何正确获取 console_scripts install_scripts 目录?
【发布时间】:2020-11-11 05:28:33
【问题描述】:

我将一个复杂的 Python 脚本拆分成一个包,以便于维护和分发。我用console_scripts 入口点和包结构创建了一个新的setup.py(使用setupmeta)。到目前为止,一切顺利。

不过,我有一些不寻常的要求:

  • 该软件包始终安装在 virtualenvwrapper 项目中,
  • 所以脚本安装在${VIRTUAL_ENV}/bin目录下...
  • ...我必须${VIRTUALENVWRAPPER_PROJECT_PATH}/bin 目录中创建一个指向脚本的符号链接。 (不要问... :-)

为此目的:

  1. 我在setup.py 脚本中添加了locate_project_path() 函数,

  2. 将以下install_and_symlink_script 子类添加到setuptools.command.install.install

    class install_and_symlink_script(install):                           
        """Do normal install, but symlink script to project directory""" 
    
        def run(self):                                                   
            install.run(self)                                            
    
            script_path = os.path.join(self.install_scripts, SCRIPT_NAME)
            project_path = locate_project_path()                         
            symlink_path = os.path.join(project_path, "bin", SCRIPT_NAME)
    
            print("creating %s script symlink" % SCRIPT_NAME)            
    
            if os.path.exists(symlink_path):                             
                print("removing existing symlink %s" % symlink_path)     
                os.unlink(symlink_path)                                  
    
            print("creating symlink from %s to %s" % (                   
                symlink_path, script_path))                              
            os.symlink(script_path, symlink_path)                        
    
  3. 并以这种方式配置setup()

    setup(
        ...
        entry_points={
            "console_scripts": ["%s=myscriptpackage.cli:main" % SCRIPT_NAME],
        },
        cmdclass={
            "install": install_and_symlink_script,
        },
        ...
    )
    

执行本地python ./setup.py install 时,包安装和符号链接创建完美。

但是当执行pip install git+ssh://.../myscriptpackage.git时,它失败了:

...
running install_egg_info
Copying src/myscriptpackage.egg-info to build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0-py2.7.egg-info
running install_scripts
creating my-script script symlink
creating symlink from /path/to/virtualenvwrapper/project/bin/my-script to build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0.data/scripts/my-script
error: [Errno 17] File exists
error
Failed building wheel for myscriptpackage
...

意思是,当通过pip而不是python ./setup.py install安装时:

  1. 它无法检测到现有的符号链接并取消链接。
  2. install_and_symlink_script.install_scripts 变量指向脚本内部构建目录而不是最终脚本安装目录... :-|

那么...您知道获得正确脚本安装目录的方法吗,与pip installpython ./setup.py install 兼容?

(顺便说一句,我在 Debian 9 下使用 python 2.7.13、setuptools 39.1.0、virtualenvwrapper 4.8.2)

更新 1

我知道error: [Errno 17] File exists 问题来自os.path.exists(symlink_path) 调用。

我刚刚明白为什么:如果符号链接是从以前的安装创建的,那么在新安装期间该符号链接会损坏。 os.path.exists 为损坏的符号链接返回 False。 OTOH,os.path.lexists 如果符号链接存在,则返回 True,无论是否损坏......

【问题讨论】:

  • 你可以在进入 setup.py 所在的路径后运行 python setup.py .. on 吗?
  • 运行python ./setup.py install 时,脚本正确安装在${VIRTUAL_ENV}/bin/ 目录中,符号链接在${PROJECT_PATH}/bin/ 目录中创建。 (setuptools.command.install.install.install_scripts 变量设置为${VIRTUAL_ENV}/bin/ 目录)。使用pip installsetuptools.command.install.install.install_scripts 变量设置为轮子内的目录,在构建目录中,不是${VIRTUAL_ENV}/bin/ 目录。我需要pip install 才能正常工作,因为我的包必须包含在requirements.txt 文件中。

标签: python pip package setuptools setup.py


【解决方案1】:

我找到了一种在通过python ./setup.py installpip install 安装时使用wheel.paths.get_install_paths() 函数持续获取脚本安装目录的方法。

我的 setuptools 自定义安装命令现在是:

...
from wheel.paths import get_install_paths

__title__ = "myscriptpackage"
...

class install_and_symlink_script(install):                            
    """Do normal install, but symlink script to project directory"""  

    def run(self):                                                    
        install.run(self)                                             

        wheel_install_paths = get_install_paths(__title__)            
        script_path = os.path.join(wheel_install_paths['scripts'], SCRIPT_NAME)                  
        # instead of: script_path = os.path.join(self.install_scripts, SCRIPT_NAME)

        project_path = locate_project_path()                          
        symlink_path = os.path.join(project_path, "bin", SCRIPT_NAME) 

        print("creating %s script symlink" % SCRIPT_NAME)             

        if os.path.lexists(symlink_path):                             
            print("removing existing symlink %s" % symlink_path)      
            os.unlink(symlink_path)                                   

        print("creating symlink from %s to %s" % (                    
            symlink_path, script_path))                               
        os.symlink(script_path, symlink_path)                         

【讨论】:

    【解决方案2】:

    我怀疑您机器上的管理员权限可能是个问题。 您能否尝试在管理员模式下运行 cmd,然后在转到 setup.py 所在的路径后,您可以运行:

     python setup.py 
    

    接下来它尝试在文件夹中创建符号链接

    build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0.data/scripts/my-script
    
    I request you to try making symlink on your own in this folder.
    

    如果这不是解决方案,则存在一些版本不匹配。 如果有帮助,请告诉我

    【讨论】:

    • 整个应用程序和软件包都安装在一个独立的virtualenv 中,而不是在系统级别,因此我不应该使用任何管理命令。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2016-02-20
    • 2021-08-09
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    相关资源
    最近更新 更多