如何正确获取 console_scripts install_scripts 目录?
How to properly get console_scripts install_scripts directory?
我将一个复杂的 Python 脚本拆分成一个包,以便于维护和分发。我创建了一个带有 console_scripts
入口点和包结构的新 setup.py
(使用 setupmeta
)。到目前为止,还不错。
不过我有一些不寻常的要求:
- 包将始终安装在
virtualenvwrapper
项目中,
- 所以脚本安装在
${VIRTUAL_ENV}/bin
目录...
- ...我 必须 创建一个指向
${VIRTUALENVWRAPPER_PROJECT_PATH}/bin
目录中的脚本的符号链接。 (不要问...:-)
为此目的:
我在setup.py
脚本中添加了一个locate_project_path()
函数,
向 setuptools.command.install.install
添加了以下 install_and_symlink_script
子类:
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
兼容?
(顺便说一句,我在 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
returns 错误的符号链接。 OTOH,os.path.lexists
returns 如果符号链接存在,则为真,无论是否损坏...
我怀疑您机器上的管理员权限可能存在问题。
您能否在管理员模式下尝试 运行ning 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.
如果这不是解决方案,则说明版本不匹配。
如果有帮助请告诉我
我找到了一种方法,可以在通过 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)
我将一个复杂的 Python 脚本拆分成一个包,以便于维护和分发。我创建了一个带有 console_scripts
入口点和包结构的新 setup.py
(使用 setupmeta
)。到目前为止,还不错。
不过我有一些不寻常的要求:
- 包将始终安装在
virtualenvwrapper
项目中, - 所以脚本安装在
${VIRTUAL_ENV}/bin
目录... - ...我 必须 创建一个指向
${VIRTUALENVWRAPPER_PROJECT_PATH}/bin
目录中的脚本的符号链接。 (不要问...:-)
为此目的:
我在
setup.py
脚本中添加了一个locate_project_path()
函数,向
setuptools.command.install.install
添加了以下install_and_symlink_script
子类: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
兼容?
(顺便说一句,我在 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
returns 错误的符号链接。 OTOH,os.path.lexists
returns 如果符号链接存在,则为真,无论是否损坏...
我怀疑您机器上的管理员权限可能存在问题。 您能否在管理员模式下尝试 运行ning 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.
如果这不是解决方案,则说明版本不匹配。 如果有帮助请告诉我
我找到了一种方法,可以在通过 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)