当执行我的 python 项目中的脚本时,如何将路径添加到 $PYTHONPATH 或 $PATH 变量?

How can I add paths to the $PYTHONPATH or $PATH variables when a script within my python project is executed?

我有一个包含多个脚本(scriptA、scriptB、scriptC)的 python 项目,这些脚本必须能够找到位于项目子路径中的不是 python 包或模块的包。组织是这样的:

|_project
  |_scriptA.py
  |_scriptB.py
  |_scriptC.py
  |_thrift_packages
    |_gen-py
        |_thriftA
          |__init__.py
          |_thriftA.py

在每个脚本的基础上,我将此目录的绝对路径添加到 sys.path

每次在项目中执行脚本时,我是否可以更改 PYTHONPATH 或 sys.path,这样我就不必将此目录的路径附加到 sys.path每个脚本的基础?

你应该在每个包中添加__init__.py,然后正确调用你所有的脚本。

|_project 
    |_scriptA.py 
    |_scriptB.py 
    |_scriptC.py 
    |__init__.py <====== Here
    |_thrift_packages 
        |__init__.py <====== Here
        |_gen-py 
        |_thriftA 
            |__init__.py 
            |_thriftA.py

假设 project 在你的 pythonpath 中,你可以这样做:

from project.thrift_packages.thriftA import thriftA

是的,你可以。

但是我认为其他答案更适合您当前的问题。 这里我只是解释一下,如何调用另一个环境,另一个当前工作目录的子进程。 这在其他情况下可以派上用场。

您可以将当前环境作为字典获取 (os.environ),将其复制到另一个字典,对其进行修改并将其传递给 supbprocess 调用。 (子流程函数有一个 env 参数)

import os
import subprocess
new_env = dict(os.environ)
new_env["PYTHONPATH"] = whateveryouwanthere  # add here the pythonpath that you want
cmd = ["mycmd.py", "myarg1", "myarg2"]  # replace with your command
subprocess.call(cmd, env=new_env)  #
# or alternatively if you also want to change the current directory
# subprocess.call(cmd, env=new_env, cwd=path_of_your_choice)  #

你有一个 XY problem,虽然是可以理解的,因为开发 Python 项目的 "proper" 方法并不明显,而且没有很多好的指南入门(对此也有不同的看法,尤其是在细节上,尽管我认为我将在这里描述的内容很普遍)。

首先,您可以在项目的根目录下创建一个 setup.py。现在这个文件可以只是一个存根;最终对它的需求应该完全消失,但一些工具仍然需要它:

$ cat setup.py
#!/usr/bin/env python
from setuptools import setup
setup()

然后创建一个setup.cfg。对于大多数 Python 项目来说,这应该足够了——您只需要在 setup.py 中为特殊情况添加额外的代码。这是更复杂的 setup.cfgtemplate,但对于您的项目,您至少需要:

$ cat setup.cfg
[metadata]
name = project
version = 0.1.0

[options]
package_dir =
    =thrift_packages/gen-py
packages = find:

现在创建并激活 virtual environment for your project(进入虚拟环境 in-depth 将超出此答案的范围,但我很乐意回答 follow-up 问题)。

$ mkdir -p ~/.virtualenvs
$ python3 -m venv ~/.virtualenvs/thrift
$ source ~/.virtualenvs/thrift/bin/activate

现在你应该有一个看起来像 (thrift) $ 的提示,表明你在一个隔离的 virtualenv 中。在这里您可以为您的包安装任何依赖项,以及包本身,而不会干扰您的主要 Python 安装。

现在以 "editable" 模式安装您的包,这意味着当您 运行 Python(包括您的 top-level 脚本):

$ pip install -e .

如果您随后启动 Python 并导入您的包,您可以看到,例如:

$ python -c 'import thriftA'; print(thriftA)
<module 'thriftA' from '/path/to/your/source/code/project/thrift_packages/gen-py/thriftA/__init__.py'>

如果这看起来太麻烦,请相信我,事实并非如此。一旦你掌握了它(并且有几个项目模板,例如用 cookie-cutter 制作来摆脱它的想法)你会发现它使路径 less麻烦)。这就是我开始任何 non-trivial 项目(不仅仅是一个文件)的方式;如果您正确设置所有内容,您将永远不必担心手动使用 sys.path$PYTHONPATH

this guide 中,虽然第一部分有点 application-specific,但如果忽略这段代码的具体用途,实际上很多内容都非常通用,尤其是标题为 [=61] 的部分=],其中更详细地重复了一些建议。

顺便说一句,如果您已经在使用 conda,则不需要创建 virtualenv,因为 conda 环境只是花哨的 virtualenvs。

以 "right" 方式执行此操作的一个优点是,当需要 安装 您的软件包时,无论是您自己还是用户,如果您 setup.cfgsetup.py 设置正确,那么所有用户要做的就是 运行 pip install .(没有 -e),它应该以相同的方式工作。