Install sudo and pg_config
Reported by Adrian Klaver | December 29th, 2012 @ 11:05 PM
There seems to an issue using sudo when installing from source or pip. setup.py complains that pg_config cannot be found on the path.
Checking the PATH shows that the directory for pg_config is indeed there.
My usual install is:
python setup.py build
This runs and the code finds the appropriate directories to build against.
sudo python setup.py install
This is where I get the error. Doing: sudo python setup.py build_ext --pg-config /path/to/pg_config install makes it complete.
If I try
sudo python setup.py build
it also fails.
If I sudo su - to root then I can do the build and install with no problem.
Something about sudo as a regular user is causing an issue.
Comments and changes to this ticket
Of course it does. PATH is an env variable: root may have a different one from your regular user.
Yes, pg_config should not be required for installing. I can try if we can look for pg_config lazily in setup.py, but wouldn't be surprised if it fails: distutils is not that straightforward.
Will look into this in the next days (unless you want to provide a patch, e.g. making pg_config_exe a lazy attribute).
Have been doing some digging around.
What I found so far.
In the sudoers file there in a setting env_reset that restricts the PATH when using sudo. There are other settings that affect PATH also and I don't think I will touch any of them.
This I can see if I:
So the root or user PATH do not apply.
This led me to the wonderful world that is distutils.
Just ran across this article which is proving helpful:
With what I have learned from it so far, I started stepping through the build/install process.
The PATH error crops up in the build_ext stage. The install command steps through that on its way to actually doing the install.
Now I have to figure out how to handle that.
Seems this is where the problem arises:
"""Complete the build system configuation.""" build_ext.finalize_options(self) pg_config_helper = PostgresConfig(self)
PostgresConfig() gets re-instantiated for each pass through build_ext.
Have not figured it out yet, but the solution would seem to be to instantiate it outside the build_ext mechanism and then pass in the values found by pg_config_helper.
Well that is not going to work. The various steps seem to take place as discrete actions with no state saved. I thought of using the pg_config setting in setup.cfg as a way of preserving state. The thing is I can not see where that setting is read in by the parser. The same goes for the include_dirs settings. Am I missing something? Still might experiment with that route, just want to make sure I am not stomping on some other process.
I am afraid the previous idea would not work for the case:
sudo python setup.py install
As soon as sudo is invoked the PATH gets restricted.
My personal short term solution is to put the following in ~/.bashrc
alias sudo='sudo env PATH=$PATH'
This adds the regular user PATH to the sudo path temporarily.
To make this happen in the script would involve invoking a process as the regular user to collect the ENV variables.
Not sure I am up to that yet.
- State changed from new to hold
- Tag set to distutils_is_a_mess, setup
I have tried making
pg_config_exea lazy property, but as you have noticed,
build_extis invoked even if only
installis asked for and no build is required.
piro@risotto:~/src/psycopg2$ python setup.py install --root=tmp running install running build running build_py running build_ext running install_lib ...
Even making the property lazy with this patch:
diff --git a/setup.py b/setup.py index 3791c14..7db1396 100644 --- a/setup.py +++ b/setup.py @@ -83,11 +83,19 @@ PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') class PostgresConfig: def __init__(self, build_ext): self.build_ext = build_ext - self.pg_config_exe = self.build_ext.pg_config - if not self.pg_config_exe: - self.pg_config_exe = self.autodetect_pg_config_path() - if self.pg_config_exe is None: - sys.stderr.write("""\ + + @property + def pg_config_exe(self): + try: + return self._pg_config_exe + except AttributeError: + pass + + self._pg_config_exe = self.build_ext.pg_config + if not self._pg_config_exe: + self._pg_config_exe = self.autodetect_pg_config_path() + if self._pg_config_exe is None: + raise Exception("""\ Error: pg_config executable not found. Please add the directory containing pg_config to the PATH @@ -99,6 +107,8 @@ or with the pg_config option in 'setup.cfg'. """) sys.exit(1) + return self._pg_config_exe + def query(self, attr_name): """Spawn the pg_config executable, querying for the given config name, and return the printed value, sanitized. """
the error is just moved from the
PostgresConfigconstructor to the
I don't see a way to detect
build_exthas no work to do before
finalize_options()is invoked and I'm not up to the distutils rabbit hole either. So I'll leave the ticket around just in case somebody feels this problem deserves a solution and shows such solution exists.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
Psycopg is the most used PostgreSQL adapter for the Python programming language. At the core it fully implements the Python DB API 2.0 specifications. Several extensions allow access to many of the features offered by PostgreSQL.