DistutilsOptionError: 必须提供 home 或 prefix/exec-prefix 之一,而不是两者都提供。

147
我通常通过pip来安装Python包。但是对于Google App Engine,我需要将包安装到另一个目录中。
我尝试过:
pip install -I flask-restful --target ./lib
但出现了以下错误:
must supply either home or prefix/exec-prefix -- not both
请问如何解决这个问题?
8个回答

292
你是否正在使用OS X和Homebrew? Homebrew Python页面https://github.com/Homebrew/brew/blob/master/docs/Homebrew-and-Python.md指出了pip的已知问题以及解决方法。
对我有用。

You can make this "empty prefix" the default by adding a ~/.pydistutils.cfg file with the following contents:

[install]
prefix=
编辑:Homebrew 页面后来被更改为建议在命令行上传递 --prefix,如下面的评论中所讨论的。这里是最后一个包含该文本的版本。不幸的是,这仅适用于 sdists,而不适用于 wheels。
问题已经报告给pip,后来修复了--user的问题。这可能是为什么该部分现在已被从Homebrew页面中删除的原因。然而,与上述问题相同,在使用--target问题仍然存在。

5
好的,链接失效了,这是我期望的新链接:https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Homebrew-and-Python.md。好东西! - patt0
6
请注意,那个文件破坏了我的虚拟环境。 - Dmytro Sadovnychyi
16
这个空前缀的问题破坏了正常的 pip install 操作 :( - Jaap
10
有人能够找到如何允许--target破坏默认的pip install行为吗? - ryantuck
3
似乎这已经不再有效了。链接已经失效,更新后的链接也没有提到pydistutils.cfg。 - Lucretiel
显示剩余5条评论

167
我相信有一个更简单的解决方案来解决这个问题(Homebrew在macOS上使用Python),它不会破坏你正常的pip操作。
你只需要在项目的根目录下创建一个setup.cfg文件,通常是主要的__init__.py或可执行py文件所在的位置。所以,如果你的项目的根文件夹是:/path/to/my/project/,就在那里创建一个setup.cfg文件并加入魔法单词即可。
[install]
prefix=  

好的,现在你应该能够在该文件夹中运行pip命令:

pip install package -t /path/to/my/project/  

这个命令只会对该文件夹运行,只需将setup.cfg复制到其他项目即可,无需在主目录下编写.pydistutils.cfg

安装模块后,可以删除setup.cfg


2
这在pip3.6上完美运行。而且我的pip仍然完好无损。 - Hannibal
10
这应该是被接受的答案。避免与全局pip设置产生问题。 - TrinitronX
10
重点在于安装后删除setup.cfg文件部分。我花了整整两天的时间试图弄清楚为什么我的虚拟环境出现了问题,错误信息如“由于EnvironmentError:[Errno 1]操作不允许:'/bin/easy_install',无法安装包”。删除设置文件后,我的头脑恢复了清晰。 - kip2
1
@kip2 是的,你说得很对,所以我已经编辑了答案来强调那一点,AndreG 请注意。 - bool.dev
谢谢您的注意。如果我说“安装模块完成后,您应该删除setup.cfg”,这样会更正确吗? - AndreG
显示剩余3条评论

24

在OSX(mac)上,假设有一个名为/var/myproject的项目文件夹

  1. cd /var/myproject
  2. 创建一个名为setup.cfg的文件,并添加以下内容: [install] prefix=
  3. 运行pip install <packagename> -t .

1
我不确定这与@AndreG的答案有何不同。 - Alastair McCormack
对我来说,这个解决方案的区别在于它进入了目录并执行了-t .,而不是停留在目录外。虽然我不知道原因,但这种方式对我有效,而另一种则无效。 - Chuck Wilbur

12

Homebrew用户的另一个解决方案是使用virtualenv

当然,这可能会自动移除目标目录的需求 - 即使没有,我发现在虚拟环境中默认情况下--target也可以工作(即在不创建/修改配置文件的情况下)。


*我说“解决方案”;也许这只是另一个精心使用虚拟环境的动机...


3
难以相信这只是一个月前的事情。我发现自己提前回答了自己的问题。 - OJFord
所以,最近我遇到了与OP问题类似的问题,而仅仅创建一个虚拟环境就解决了我的问题。我仍然可以安装到目标目录中。我的问题更为复杂,因为我还安装了Python3,但是对于虚拟环境解决方案点个赞。 - Josh Brown

3

我尝试了其他一些关于--install-option="--prefix=lib"的建议,但都出现了错误。我发现唯一可行的方法是使用PYTHONUSERBASE,如此处所述。

export PYTHONUSERBASE=lib
pip install -I flask-restful --user

这并不完全等同于--target,但在任何情况下都对我产生了作用。


2
如果您正在使用virtualenv*,最好再次检查您正在使用哪个pip
如果您看到类似于/usr/local/bin/pip的内容,则已经退出了您的环境。重新激活您的virtualenv将解决此问题:
VirtualEnv:$ source bin/activate VirtualFish:$ vf activate [environ] *:我使用virtualfish,但我认为这个提示对两者都适用。

使用 virtualenv 实际上是我类似情况的解决方案 :) - chriscatfr

2

正如其他人提到的那样,这是pip和使用homebrew安装的python已知的bug。

如果您创建一个包含“空前缀”指令的~/.pydistutils.cfg文件,它将修复此问题,但会破坏正常的pip操作。

在官方解决此bug之前,其中一个选项是创建自己的bash脚本来处理此情况:

 #!/bin/bash

 name=''
 target=''

 while getopts 'n:t:' flag; do
     case "${flag}" in
         n) name="${OPTARG}" ;;
         t) target="${OPTARG}" ;;
     esac
 done

 if [ -z "$target" ];
 then
     echo "Target parameter must be provided"
     exit 1
 fi

 if [ -z "$name" ];
 then
     echo "Name parameter must be provided"
     exit 1
 fi

 # current workaround for homebrew bug
 file=$HOME'/.pydistutils.cfg'
 touch $file

 /bin/cat <<EOM >$file
 [install]
 prefix=
 EOM
 # end of current workaround for homebrew bug

 pip install -I $name --target $target

 # current workaround for homebrew bug
 rm -rf $file
 # end of current workaround for homebrew bug

这个脚本包装了你的命令,并且:
  1. 接受名称和目标参数
  2. 检查这些参数是否为空
  3. 创建一个包含“空前缀”指令的~/.pydistutils.cfg文件
  4. 使用提供的参数执行你的pip命令
  5. 删除~/.pydistutils.cfg文件
这个脚本可以根据你的需求进行更改和适应,但是它允许你在不破坏pip的情况下运行你的命令。希望能对你有所帮助 :)

-1

我有一个类似的问题。 我使用--system标志来避免错误,就像我在这里描述的其他线程中解释我的具体情况一样。 我在这里发布帖子,希望能帮助任何面临相同问题的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接