伙计,
我将复杂的Python脚本拆分为一个程序包,以便于维护和分发。我使用setup.py
入口点和包结构创建了一个全新的setupmeta
(使用console_scripts
)。到目前为止,一切都很好。
不过,我有一些不寻常的要求:
virtualenvwrapper
项目中,${VIRTUAL_ENV}/bin
目录中... ${VIRTUALENVWRAPPER_PROJECT_PATH}/bin
目录中创建一个针对脚本的符号链接。 (不要问...:-)为此,
locate_project_path()
脚本中添加了setup.py
函数,将以下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)
并通过以下方式配置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
安装时:
install_and_symlink_script.install_scripts
变量指向构建目录内的脚本 而不是最终脚本安装目录...:-| 那么...您知道一种获取正确的脚本安装目录的方法,该目录与pip install
和python ./setup.py install
兼容吗?
(顺便说一句,我正在使用python 2.7.13,setuptools 39.1.0,Debian 9下的virtualenvwrapper 4.8.2)
我知道error: [Errno 17] File exists
的问题来自于os.path.exists(symlink_path)
的电话。
我只是理解为什么:如果从以前的安装中创建了符号链接,则在新安装期间该符号链接会中断。 os.path.exists
对于断开的符号链接返回False。 OTOH,如果符号链接存在,损坏或不存在,os.path.lexists
返回True
答案 0 :(得分:0)
我怀疑您机器上的管理员权限可能是一个问题。 能否请您尝试在管理员模式下运行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.
如果这不是解决方案,则说明版本不匹配。 请告诉我是否有帮助
答案 1 :(得分:0)
当使用python ./setup.py install
函数通过pip 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)