通过 pipenv 自定义模块搜索路径 (PYTHONPATH)
Customize module search path (PYTHONPATH) via pipenv
我有一个 Python 项目,包括一个 Jupyter 笔记本、bin
目录中的几个脚本和 src
目录中的模块,以及 Pipfile
中的依赖项:
myproject
├── myproject.ipynb
├── Pipfile
├── Pipfile.lock
├── bin
│ ├── bar.py
│ └── foo.py
└── src
├── baz.py
└── qux.py
脚本 foo.py
和 bar.py
使用标准 shebang
#!/usr/bin/env python
并且可以 运行 与 pipenv shell
:
mymachine:myproject myname$ pipenv shell
(myproject-U308romt) bash-3.2$ bin/foo.py
foo
但是,我无法从脚本轻松访问 src
中的模块。如果我添加
import src.baz as baz
到foo.py
,我得到:
ModuleNotFoundError: No module named 'src'
我尝试的一个解决方案是在 myproject
下添加一个 .env
文件:
PYTHONPATH=${PYTHONPATH}:${PWD}
感谢 pipenv
的 automatic loading of .env
,但将 .env
文件签入项目的 git 分发版会与 .env
的传统用法发生冲突=26=] 来存储密码等秘密——事实上,我的 Python 项目的默认 .gitignore
已经排除了 .env
正是出于这个原因。
$ git add .env
The following paths are ignored by one of your .gitignore files:
.env
Use -f if you really want to add them.
或者,我可以将 src
移动到 bin
下,但这样 Jupyter notebook 就必须将模块引用为 bin.src.baz
等,这也很麻烦。
我目前的解决方法是添加一个符号链接:
myproject
├── Pipfile
├── Pipfile.lock
├── bin
│ ├── bar.py
│ ├── foo.py
│ └── src -> ../src
└── src
├── baz.py
└── qux.py
这行得通,我想它的好处是透明,但似乎应该有一些方法可以利用 pipenv
来解决同样的问题。
是否有可移植的、可分发的方式将这些模块放在搜索路径上?
我不确定是否有完美的解决方案,但为了显式而不是隐式 (PEP 20),我决定在 运行 任何脚本之前签入需要获取的文件。这是一个额外的手动步骤,但您可以将其放入 Makefile 中。
env.sh
export PYTHONPATH=${PYTHONPATH}:${PWD}
生成文件
bar:
source env.sh && pipenv run python scripts/bar.py
.PHONY: migrate
该解决方案有点类似于 Go 的方法 GOPATH
。
我认为其他解决方案都没有那么好:
pipenv
旨在解决依赖关系,我可能是错的但是我没有找到任何与PYTHONPATH
. 问题相关的东西
- 如果您开始使用其他脚本文件夹,链接文件夹将无法很好地扩展。
(来这里回答,结果给了一个)
我有一个类似的项目文件夹结构,所以我遇到了同样的问题。
感谢您的提示,我的解决方案是在 Pipfile
的同一级别添加一个文件 .env
,内容如下:
$ cat .env
PYTHONPATH=${PYTHONPATH}:src
现在,用
之类的东西启动我的应用程序
$ pipenv run python -m package.subpackage.app
似乎在我的项目文件夹及其子文件夹中工作正常。
旁注(虽然这不是 good/clean 做事的方式):
对于您的 ModuleNotFoundError: No module named 'src'
问题...... "problem" 是 src
(文件夹)不是一个包,为了解决这个问题,您可以轻松添加(空) __init__.py
文件在 src
文件夹中,因此将其设为 "package";这反过来会使 import src.baz
成为可能。
(稍后编辑)
其实这在sys.path
中添加了一条记录<project_folder>/${PYTHONPATH}
,没有用,所以.env
文件的正确内容应该只是PYTHONPATH=src
.
您可能可以使用两个单独的 .env 文件。一个用于您的密码,一个用于其他地方的 pipenv。您可以通过在环境中设置 PIPENV_DOTENV_LOCATION 变量来为您的 pipenv .env 文件使用自定义路径。
如果你认为这个便携,是否必须先设置变量,这是有争议的。
无论如何,根据经验,您不应该过于依赖 .env 的自动加载。如果您正在使用 remote/ssh interpeters 或并行使用多个环境进行测试,最干净的方法是将您的项目路径添加到 Python 环境的 site-packages 文件夹中的 *.pth 文件.在 conda 中有一个明确的“开发”命令,在 pipenv 中你仍然需要手动完成。不过,这就是方法,因为您在任意设置中明确为您的项目创建了 Python 环境,然后您还应该将项目位置硬连接到此设置中。
我有一个 Python 项目,包括一个 Jupyter 笔记本、bin
目录中的几个脚本和 src
目录中的模块,以及 Pipfile
中的依赖项:
myproject
├── myproject.ipynb
├── Pipfile
├── Pipfile.lock
├── bin
│ ├── bar.py
│ └── foo.py
└── src
├── baz.py
└── qux.py
脚本 foo.py
和 bar.py
使用标准 shebang
#!/usr/bin/env python
并且可以 运行 与 pipenv shell
:
mymachine:myproject myname$ pipenv shell
(myproject-U308romt) bash-3.2$ bin/foo.py
foo
但是,我无法从脚本轻松访问 src
中的模块。如果我添加
import src.baz as baz
到foo.py
,我得到:
ModuleNotFoundError: No module named 'src'
我尝试的一个解决方案是在 myproject
下添加一个 .env
文件:
PYTHONPATH=${PYTHONPATH}:${PWD}
感谢 pipenv
的 automatic loading of .env
,但将 .env
文件签入项目的 git 分发版会与 .env
的传统用法发生冲突=26=] 来存储密码等秘密——事实上,我的 Python 项目的默认 .gitignore
已经排除了 .env
正是出于这个原因。
$ git add .env
The following paths are ignored by one of your .gitignore files:
.env
Use -f if you really want to add them.
或者,我可以将 src
移动到 bin
下,但这样 Jupyter notebook 就必须将模块引用为 bin.src.baz
等,这也很麻烦。
我目前的解决方法是添加一个符号链接:
myproject
├── Pipfile
├── Pipfile.lock
├── bin
│ ├── bar.py
│ ├── foo.py
│ └── src -> ../src
└── src
├── baz.py
└── qux.py
这行得通,我想它的好处是透明,但似乎应该有一些方法可以利用 pipenv
来解决同样的问题。
是否有可移植的、可分发的方式将这些模块放在搜索路径上?
我不确定是否有完美的解决方案,但为了显式而不是隐式 (PEP 20),我决定在 运行 任何脚本之前签入需要获取的文件。这是一个额外的手动步骤,但您可以将其放入 Makefile 中。
env.sh
export PYTHONPATH=${PYTHONPATH}:${PWD}
生成文件
bar:
source env.sh && pipenv run python scripts/bar.py
.PHONY: migrate
该解决方案有点类似于 Go 的方法 GOPATH
。
我认为其他解决方案都没有那么好:
pipenv
旨在解决依赖关系,我可能是错的但是我没有找到任何与PYTHONPATH
. 问题相关的东西
- 如果您开始使用其他脚本文件夹,链接文件夹将无法很好地扩展。
(来这里回答,结果给了一个)
我有一个类似的项目文件夹结构,所以我遇到了同样的问题。
感谢您的提示,我的解决方案是在 Pipfile
的同一级别添加一个文件 .env
,内容如下:
$ cat .env
PYTHONPATH=${PYTHONPATH}:src
现在,用
之类的东西启动我的应用程序$ pipenv run python -m package.subpackage.app
似乎在我的项目文件夹及其子文件夹中工作正常。
旁注(虽然这不是 good/clean 做事的方式):
对于您的 ModuleNotFoundError: No module named 'src'
问题...... "problem" 是 src
(文件夹)不是一个包,为了解决这个问题,您可以轻松添加(空) __init__.py
文件在 src
文件夹中,因此将其设为 "package";这反过来会使 import src.baz
成为可能。
(稍后编辑)
其实这在sys.path
中添加了一条记录<project_folder>/${PYTHONPATH}
,没有用,所以.env
文件的正确内容应该只是PYTHONPATH=src
.
您可能可以使用两个单独的 .env 文件。一个用于您的密码,一个用于其他地方的 pipenv。您可以通过在环境中设置 PIPENV_DOTENV_LOCATION 变量来为您的 pipenv .env 文件使用自定义路径。 如果你认为这个便携,是否必须先设置变量,这是有争议的。
无论如何,根据经验,您不应该过于依赖 .env 的自动加载。如果您正在使用 remote/ssh interpeters 或并行使用多个环境进行测试,最干净的方法是将您的项目路径添加到 Python 环境的 site-packages 文件夹中的 *.pth 文件.在 conda 中有一个明确的“开发”命令,在 pipenv 中你仍然需要手动完成。不过,这就是方法,因为您在任意设置中明确为您的项目创建了 Python 环境,然后您还应该将项目位置硬连接到此设置中。