34

我有一个 Python 项目,它由一个 Jupyter 笔记本、一个目录中的多个脚本和一个bin目录中的模块组成src,依赖项位于Pipfile

myproject
├── myproject.ipynb
├── Pipfile
├── Pipfile.lock
├── bin
│   ├── bar.py
│   └── foo.py
└── src
    ├── baz.py
    └── qux.py

脚本foo.pybar.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'

我尝试的一种解决方案是在.env下面添加一个文件myproject

PYTHONPATH=${PYTHONPATH}:${PWD}

这要归功于pipenv自动加载.env,但是将.env文件检入到项目的 git 发行版中会与存储密码等机密的传统用法发生冲突.env——事实上,我.gitignore对 Python 项目的默认设置已经排除.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.

或者,我可以移到srcbin,但是 Jupyter 笔记本必须引用模块bin.src.baz等,这也很麻烦。

我目前的解决方法是添加一个符号链接:

myproject
├── Pipfile
├── Pipfile.lock
├── bin
│   ├── bar.py
│   ├── foo.py
│   └── src -> ../src
└── src
    ├── baz.py
    └── qux.py

这行得通,我想有透明的好处,但似乎应该有一些方法可以利用pipenv来解决同样的问题。

是否有一种可移植的、可分发的方式将这些模块放在搜索路径上?

4

3 回答 3

19

我不确定是否有完美的解决方案,但为了明确而不是隐含PEP 20),我决定在运行任何脚本之前签入需要获取的文件。这是一个额外的手动步骤,但您可以将其放入 Makefile 中。

环境文件

export PYTHONPATH=${PYTHONPATH}:${PWD}

生成文件

bar:
    source env.sh && pipenv run python scripts/bar.py
.PHONY: migrate

该解决方案有点类似于 Go 使用GOPATH.

我认为其他解决方案没有那么好:

  • pipenv旨在解决依赖关系,我可能是错的,但我没有找到任何与PYTHONPATH.
  • 如果您开始拥有其他脚本文件夹,则链接文件夹将无法很好地扩展。
于 2018-04-12T13:23:49.337 回答
12

(来这里是为了回答,最后还是给了一个)

我有一个类似的项目文件夹结构,所以我遇到了同样的问题。
感谢您的提示,我的解决方案是添加与以下内容.env相同级别的文件:Pipfile

$ cat .env
PYTHONPATH=${PYTHONPATH}:src

现在,用类似的东西启动我的应用程序

$ pipenv run python -m package.subpackage.app

似乎在我的项目文件夹中以及它的子文件夹中都可以正常工作。

旁注(虽然不是一个好的/干净的做事方式):
对于你的ModuleNotFoundError: No module named 'src'问题......“问题”是src(文件夹)不是一个包,为了解决你可以轻松添加一个(空)__init__.py文件夹内的src文件,将其设为“包”;这反过来又使成为import src.baz可能。

(稍后编辑)
实际上这在 中添加了一条记录<project_folder>/${PYTHONPATH}sys.path这是无用的,因此.env文件的正确内容应该只有PYTHONPATH=src.

于 2019-01-07T22:26:19.950 回答
0

您可能可以使用两个单独的 .env 文件。一个用于您的密码,一个用于其他地方的 pipenv。您可以通过在环境中设置 PIPENV_DOTENV_LOCATION 变量来为您的 pipenv .env 文件使用自定义路径。如果您考虑这种可移植性,如果您必须首先设置变量,这是有争议的。

无论如何,根据经验,您不应过于依赖 .env 的自动加载。如果您使用远程/ssh interpeters 或有多个并行环境用于测试目的,最简洁的方法是将您的项目路径添加到 Python 环境的 site-packages 文件夹中的 *.pth 文件。在 conda 中有一个明确的“开发”命令,但在 pipenv 中你仍然必须手动完成。尽管如此,这仍然是一种方式,因为您在任意设置中为您的项目显式创建 Python 环境,然后您还应该将项目位置硬连接到此设置中。

于 2021-07-26T09:17:11.117 回答