RHEL 9+系统下/usr/local/bin中Python脚本的依赖组织方案及共享代码存放规范咨询
回答:Python共享代码在RHEL RPM包中的最佳部署路径
首先直接给结论:把非独立可执行的Python共享代码(比如你的deps.py)放在/usr/local/bin确实不是最佳实践,原因和更规范的替代方案我给你详细拆解下:
为什么不建议放/usr/local/bin?
按照Filesystem Hierarchy Standard (FHS)的定义,/usr/local/bin是专门用来存放用户安装的可执行程序的目录——也就是那些可以直接运行的脚本或二进制文件。把非可执行的模块文件放在这里会带来几个实际问题:
- 混淆目录用途:其他维护人员或自动化工具扫描这个目录时,会默认认为里面的文件都是可执行的,容易造成误解或误操作。
- 潜在冲突风险:如果未来有其他工具也命名为
deps.py并安装到这个目录,会直接覆盖你的文件。 - 不符合Python生态规范:Python的模块有标准的存放路径,硬塞到可执行目录里,会让你的部署结构显得混乱,后续排查依赖问题也更麻烦。
推荐的替代方案
针对你的RPM打包场景,这里有几个更规范的做法:
1. 放到系统Python的site-packages目录
这是最符合Python规范的做法:
- 把
deps.py安装到/usr/local/lib/pythonX.Y/site-packages/(RHEL9默认Python版本是3.9,所以对应路径是/usr/local/lib/python3.9/site-packages/)。 - 在你的Python脚本里直接通过
import deps就能引用共享代码,不需要额外修改sys.path。 - 在RPM spec文件里可以这样写安装逻辑:
%install install -m 0644 deps.py %{buildroot}/usr/local/lib/python3.9/site-packages/ install -m 0755 your-executable-script.py %{buildroot}/usr/local/bin/
2. 创建专属的应用库目录
如果担心系统site-packages里的模块太多,怕和其他包冲突,可以为你的应用创建一个专属目录:
- 比如
/usr/local/lib/your-app-name/,把deps.py放在这里。 - 然后在每个可执行脚本的开头添加路径声明:
import sys sys.path.append('/usr/local/lib/your-app-name/') import deps - 或者更优雅一点,在你的systemd服务文件里设置
PYTHONPATH环境变量,这样所有通过systemd启动的脚本都会自动识别这个路径:[Service] Environment="PYTHONPATH=/usr/local/lib/your-app-name" ExecStart=/usr/local/bin/your-script.py - RPM spec里记得把这个目录和文件加入
%files段,确保安装卸载正常:%files /usr/local/lib/your-app-name/ /usr/local/bin/your-executable-script.py
3. 把共享代码做成正式的Python包
如果你的共享代码未来可能扩展,建议把它做成一个标准的Python包(比如命名为your_app_deps):
- 哪怕只是单个模块,也可以创建
your_app_deps/目录,里面放__init__.py和deps.py(或者直接把代码写在__init__.py里)。 - 用
setup.py或pyproject.toml定义这个包的元信息,打包成wheel或egg文件后,通过RPM安装到系统site-packages。 - 这种方式的好处是可以更好地管理版本、依赖,也符合Python社区的最佳实践,后续扩展功能更方便。
额外注意事项
- 权限设置:共享模块文件的权限建议设为
0644(只读给其他用户),可执行脚本设为0755,在RPM安装时要分别指定。 - Python版本兼容:RHEL9默认绑定Python3.9,要确保你的代码适配这个版本,或者在RPM spec里明确依赖
python39包。 - RPM清理逻辑:如果用自定义目录,记得在RPM的
%postun脚本里处理空目录的删除(比如当最后一个文件被卸载时,删除/usr/local/lib/your-app-name/)。
总之,虽然把共享代码放在/usr/local/bin能临时解决问题,但从长期维护和规范的角度来看,上面的替代方案会更合适。
内容的提问来源于stack exchange,提问作者kmalarski




