Python跨平台控制台脚本部署疑问:scripts与console_scripts适配问题
pip install .后console_scripts可执行脚本路径问题 我来帮你分析下这个问题的根源,再给你两个可行的解决方案——核心原因其实是开发模式和正常安装模式下Python路径的差异:
- 当你用
pip install -e .(开发模式)时,你的项目根目录会被直接添加到Python的sys.path里,所以哪怕scripts目录不是一个正式的Python包,Python也能找到里面的脚本模块; - 但用
pip install .正常安装时,只有my_package会被安装到系统的site-packages目录,scripts目录默认不会被打包进去,这就导致你通过console_scripts配置的入口点找不到对应的模块了。
推荐方案:规范打包结构,将脚本逻辑迁移到package内
这是Python打包的最佳实践,既能完美解决跨平台问题,也方便后续维护:
在
my_package里新建一个专门处理命令行入口的模块,比如cli.py:# my_package/cli.py # 导入你package里的核心功能 from .modules import your_function_here def abc_main(): # 这里放原来scripts/abc里的所有逻辑,或者直接调用核心功能 print("Executing abc command") # your_function_here() def def_main(): # 同理处理scripts/def的逻辑 print("Executing def command")修改
setup.py的entry_points配置,指向这个新模块的函数:# setup.py from setuptools import setup, find_packages setup( name="my_package", version="0.1.0", packages=find_packages(), entry_points={ "console_scripts": [ "abc=my_package.cli:abc_main", "def=my_package.cli:def_main" ] } )现在不管是开发模式还是正常安装,
abc和def命令都能正常运行了——因为console_scripts会自动生成对应平台的可执行文件(Windows下是.exe,Linux/macOS是可执行脚本),而且这些生成的文件会正确指向安装在site-packages里的my_package.cli模块,完全没有路径问题。如果想保留原来的
scripts目录做本地测试,可以把原脚本改成简单的调用 wrapper:# scripts/abc #!/usr/bin/env python3 from my_package.cli import abc_main abc_main()这样本地运行脚本也能正常工作,同时不影响安装后的命令。
备选方案:将scripts目录作为Python包打包(不推荐)
如果你实在不想移动脚本逻辑,可以把scripts目录改成一个正式的Python包,让它被一起安装到site-packages:
在
scripts目录下添加__init__.py(空文件即可),并把原来的abc、def脚本改成带.py后缀的文件(比如abc.py):working folder ├── my_package │ ├── __init__.py │ ├── modules.py ├── scripts │ ├── __init__.py │ ├── abc.py │ └── def.py └── setup.py修改脚本文件,添加
main()函数(因为console_scripts需要指向一个可调用的函数):# scripts/abc.py def main(): # 原来的脚本逻辑 print("Running abc script") if __name__ == "__main__": main()修改
setup.py,把scripts包包含到安装内容中:# setup.py from setuptools import setup, find_packages setup( name="my_package", version="0.1.0", packages=find_packages(include=["my_package", "scripts"]), entry_points={ "console_scripts": [ "abc=scripts.abc:main", "def=scripts.def:main" ] } )
这样安装后scripts包会被放到site-packages里,console_scripts的入口点就能找到对应的模块了。不过这种方式会把脚本逻辑和核心代码分离,长期来看不利于维护,所以还是推荐第一种方案。
内容的提问来源于stack exchange,提问作者Ryan




