通过pipenv自定义模块搜索路径(PYTHONPATH)

时间:2018-04-06 18:45:25

标签: python python-3.x pythonpath pipenv

我有一个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的{​​{3}},但将.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.

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

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

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

这是有效的,我认为有透明的好处,但似乎应该有一些方法来利用pipenv来解决同样的问题。

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

3 个答案:

答案 0 :(得分:10)

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

<强> env.sh

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

<强>生成文件

GOPATH

解决方案有点类似于Go采用pipenv的方法。

我认为其他解决方案不太好:

  • PYTHONPATH旨在解决依赖关系,我可能错了,但我找不到任何与FILE.md问题相关的内容。
  • 如果您开始使用其他脚本文件夹,则链接文件夹不会很好地扩展。

答案 1 :(得分:2)

(来这里是一个答案,最终给了一个答案)

我有一个类似的项目文件夹结构,所以我遇到了同样的问题。
多亏了您的提示,我的解决方案是在与.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

答案 2 :(得分:0)

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

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