DistutilsOptionError: must supply either home or prefix/exec-prefix — not both
Question:
I’ve been usually installed python packages through pip.
For Google App Engine, I need to install packages to another target directory.
I’ve tried:
pip install -I flask-restful –target ./lib
but it fails with:
must supply either home or prefix/exec-prefix — not both
How can I get this to work?
Answers:
Are you using OS X and Homebrew? The Homebrew python page https://github.com/Homebrew/brew/blob/master/docs/Homebrew-and-Python.md calls out a known issue with pip and a work around.
Worked for me.
You can make this "empty prefix" the default by adding a
~/.pydistutils.cfg file with the following contents:
[install]
prefix=
Edit: The Homebrew page was later changed to recommend passing --prefix
on the command line, as discussed in the comments below. Here is the last version which contained that text. Unfortunately this only works for sdists, not wheels.
The issue was reported to pip, which later fixed it for --user
. That’s probably why the section has now been removed from the Homebrew page. However, the problem still occurs when using --target
as in the question above.
Another solution* for Homebrew users is simply to use a virtualenv
.
Of course, that may remove the need for the target directory anyway – but even if it doesn’t, I’ve found --target
works by default (as in, without creating/modifying a config file) when in a virtual environment.
*I say solution; perhaps it’s just another motivation to meticulously use venvs…
I hit errors with the other recommendations around --install-option="--prefix=lib"
. The only thing I found that worked is using PYTHONUSERBASE
as described here.
export PYTHONUSERBASE=lib
pip install -I flask-restful --user
this is not exactly the same as --target
, but it does the trick for me in any case.
As other mentioned, this is known bug with pip & python installed with homebrew.
If you create ~/.pydistutils.cfg
file with “empty prefix” instruction it will fix this problem but it will break normal pip operations.
Until this bug is officially addressed, one of the options would be to create your own bash script that would handle this case:
#!/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
This script wraps your command and:
- accepts name and target parameters
- checks if those parameters are empty
- creates
~/.pydistutils.cfg
file with “empty prefix” instruction in it
- executes your pip command with provided parameters
- removes
~/.pydistutils.cfg
file
This script can be changed and adapted to address your needs but you get idea. And it allows you to run your command without braking pip. Hope it helps 🙂
I believe there is a simpler solution to this problem (Homebrew’s Python on macOS) that won’t break your normal pip operations.
All you have to do is to create a setup.cfg
file at the root directory of your project, usually where your main __init__.py
or executable py file is. So if the root folder of your project is: /path/to/my/project/
, create a setup.cfg
file in there and put the magic words inside:
[install]
prefix=
OK, now you sould be able to run pip’s commands for that folder:
pip install package -t /path/to/my/project/
This command will run gracefully for that folder only. Just copy setup.cfg
to whatever other projects you might have. No need to write a .pydistutils.cfg
on your home directory.
After you are done installing the modules, you may remove setup.cfg
.
I have a similar issue.
I use the –system flag to avoid the error as I decribe here on other thread where I explain the specific case of my situation.
I post this here expecting that can help anyone facing the same problem.
On OSX(mac), assuming a project folder called /var/myproject
cd /var/myproject
- Create a file called
setup.cfg
and add
[install]
prefix=
- Run
pip install <packagename> -t .
If you’re using virtualenv*, it might be a good idea to double check which pip
you’re using.
If you see something like /usr/local/bin/pip
you’ve broken out of your environment. Reactivating your virtualenv will fix this:
VirtualEnv: $ source bin/activate
VirtualFish: $ vf activate [environ]
*: I use virtualfish, but I assume this tip is relevant to both.
I’ve been usually installed python packages through pip.
For Google App Engine, I need to install packages to another target directory.
I’ve tried:
pip install -I flask-restful –target ./lib
but it fails with:
must supply either home or prefix/exec-prefix — not both
How can I get this to work?
Are you using OS X and Homebrew? The Homebrew python page https://github.com/Homebrew/brew/blob/master/docs/Homebrew-and-Python.md calls out a known issue with pip and a work around.
Worked for me.
You can make this "empty prefix" the default by adding a
~/.pydistutils.cfg file with the following contents:[install] prefix=
Edit: The Homebrew page was later changed to recommend passing --prefix
on the command line, as discussed in the comments below. Here is the last version which contained that text. Unfortunately this only works for sdists, not wheels.
The issue was reported to pip, which later fixed it for --user
. That’s probably why the section has now been removed from the Homebrew page. However, the problem still occurs when using --target
as in the question above.
Another solution* for Homebrew users is simply to use a virtualenv
.
Of course, that may remove the need for the target directory anyway – but even if it doesn’t, I’ve found --target
works by default (as in, without creating/modifying a config file) when in a virtual environment.
*I say solution; perhaps it’s just another motivation to meticulously use venvs…
I hit errors with the other recommendations around --install-option="--prefix=lib"
. The only thing I found that worked is using PYTHONUSERBASE
as described here.
export PYTHONUSERBASE=lib
pip install -I flask-restful --user
this is not exactly the same as --target
, but it does the trick for me in any case.
As other mentioned, this is known bug with pip & python installed with homebrew.
If you create ~/.pydistutils.cfg
file with “empty prefix” instruction it will fix this problem but it will break normal pip operations.
Until this bug is officially addressed, one of the options would be to create your own bash script that would handle this case:
#!/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
This script wraps your command and:
- accepts name and target parameters
- checks if those parameters are empty
- creates
~/.pydistutils.cfg
file with “empty prefix” instruction in it - executes your pip command with provided parameters
- removes
~/.pydistutils.cfg
file
This script can be changed and adapted to address your needs but you get idea. And it allows you to run your command without braking pip. Hope it helps 🙂
I believe there is a simpler solution to this problem (Homebrew’s Python on macOS) that won’t break your normal pip operations.
All you have to do is to create a setup.cfg
file at the root directory of your project, usually where your main __init__.py
or executable py file is. So if the root folder of your project is: /path/to/my/project/
, create a setup.cfg
file in there and put the magic words inside:
[install]
prefix=
OK, now you sould be able to run pip’s commands for that folder:
pip install package -t /path/to/my/project/
This command will run gracefully for that folder only. Just copy setup.cfg
to whatever other projects you might have. No need to write a .pydistutils.cfg
on your home directory.
After you are done installing the modules, you may remove setup.cfg
.
I have a similar issue.
I use the –system flag to avoid the error as I decribe here on other thread where I explain the specific case of my situation.
I post this here expecting that can help anyone facing the same problem.
On OSX(mac), assuming a project folder called /var/myproject
cd /var/myproject
- Create a file called
setup.cfg
and add
[install]
prefix=
- Run
pip install <packagename> -t .
If you’re using virtualenv*, it might be a good idea to double check which pip
you’re using.
If you see something like /usr/local/bin/pip
you’ve broken out of your environment. Reactivating your virtualenv will fix this:
VirtualEnv: $ source bin/activate
VirtualFish: $ vf activate [environ]
*: I use virtualfish, but I assume this tip is relevant to both.