如何在任意目录使用Poetry虚拟环境运行Python脚本
问题背景
更新说明
以下工作流在命令行安装和运行Python脚本时表现良好:
- 第一步,在Poetry的
pyproject.toml文件中为脚本配置入口点:[tool.poetry.scripts] <command_line_command> = "<python_module>:main" - 第二步,调用
pipx install安装脚本,使其可像其他CLI程序一样在命令行执行。
我的Python脚本需搜索当前工作目录下的文件,且依赖Poetry虚拟环境提供的Python包,但遇到以下问题:
- 直接执行脚本会触发
ModuleNotFoundError,原因是未激活包含依赖的虚拟环境:alias script="/path/to/script.py" script ModuleNotFoundError: - 尝试用
poetry run激活虚拟环境,但截至2023年6月23日,该命令无法指定pyproject.toml所在目录,导致报错:alias script="poetry run /path/to/script.py" script Poetry could not find a pyproject.toml file - 先切换到项目目录(
cd /path/to)再执行poetry run,虽能激活环境并运行脚本,但脚本会默认搜索项目目录的文件,无法在任意目标目录执行搜索操作。 - 直接激活虚拟环境
/<virtual_environment>/bin/activate可行,但Poetry创建的虚拟环境名称带有随机哈希后缀,需先查找确定具体路径。
需求:如何在不切换工作目录的任意目录下,使用Poetry虚拟环境运行该Python脚本?
解决方案
方法1:直接调用Poetry虚拟环境的Python解释器
- 在项目目录下执行以下命令,获取虚拟环境的Python路径:
输出示例:poetry run which python/home/user/.cache/pypoetry/virtualenvs/your-project-abc123/bin/python - 创建别名,用该路径直接执行脚本:
此方式下,脚本会使用Poetry虚拟环境的依赖,同时以当前工作目录为搜索目标,不受项目目录限制。alias script="/path/to/poetry-virtualenv-python /path/to/script.py"
方法2:动态获取虚拟环境路径的Shell函数
创建一个Shell函数,自动获取项目虚拟环境路径并执行脚本,无需硬编码路径:
script() { # 切换到项目目录获取虚拟环境的Python可执行文件路径 PYTHON_PATH=$(cd /path/to/your/project && poetry env info --executable) # 用该Python执行脚本,并传递所有命令行参数 "$PYTHON_PATH" /path/to/script.py "$@" }
将上述函数添加到你的Shell配置文件(如~/.bashrc或~/.zshrc),执行source ~/.bashrc(或对应配置文件)生效后,即可在任意目录执行script,还能传递参数给脚本。
方法3:让脚本自动加载Poetry环境
在脚本开头添加一段代码,自动检测并切换到正确的Poetry环境,同时保留当前工作目录:
import os import subprocess import sys # 替换为你的项目目录(pyproject.toml所在路径) PROJECT_DIR = "/path/to/your/project" try: # 尝试导入依赖包,验证是否在正确环境中 import your_dependency_package except ImportError: # 若不在正确环境,调用poetry run重新执行脚本 cmd = ["poetry", "run", sys.executable] + sys.argv # 切换到项目目录让Poetry找到配置,但subprocess默认继承当前工作目录 subprocess.run(cmd, cwd=PROJECT_DIR, check=True) sys.exit() # 脚本原有逻辑 def main(): # 获取当前工作目录(即执行脚本时的目录) target_dir = os.getcwd() # 执行文件搜索逻辑... if __name__ == "__main__": main()
这样执行脚本时,若环境不符合要求,会自动通过Poetry虚拟环境重新启动脚本,且脚本仍以当前执行目录为搜索目标。
方法4:打包安装脚本并传递当前目录参数
若你的脚本支持接收目标目录作为参数,可按以下步骤操作:
- 在项目目录执行打包命令:
poetry build - 将包安装到Poetry虚拟环境:
poetry run pip install dist/your-package-*.whl - 创建别名,将当前工作目录作为参数传递给脚本:
此方式中,alias script="cd /path/to/your/project && poetry run <command_line_command> \"$PWD\" && cd -"cd -会回到原工作目录,脚本则以你传入的$PWD(当前执行目录)作为搜索目标。
内容的提问来源于stack exchange,提问作者user2514157
相关产品推荐
相关产品推荐

