This project is archived and is in readonly mode.

#144 ✓ hold
Adrian Klaver

Install sudo and pg_config

Reported by Adrian Klaver | December 29th, 2012 @ 11:05 PM

os-linux
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

  • Daniele Varrazzo

    Daniele Varrazzo December 30th, 2012 @ 08:33 AM

    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).

  • Adrian Klaver

    Adrian Klaver December 30th, 2012 @ 03:47 PM

    The PATH for root also contains the pg_config directory. As I said in the original problem report, when I run build/install entirely as root there is no problem. It is the usage of sudo that cause the issue.

  • Adrian Klaver

    Adrian Klaver December 30th, 2012 @ 10:13 PM

    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:

    print os.environ['PATH']
    

    in

    def find_on_path()
    

    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:
    http://www.python.org/files/sigs/sc_submission.html
    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.

  • Adrian Klaver

    Adrian Klaver December 30th, 2012 @ 10:39 PM

    Seems this is where the problem arises:

    def finalize_options(self):

        """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.

  • Adrian Klaver

    Adrian Klaver December 31st, 2012 @ 03:33 AM

    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.

  • Adrian Klaver

    Adrian Klaver December 31st, 2012 @ 03:59 PM

    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.

  • Daniele Varrazzo

    Daniele Varrazzo January 9th, 2013 @ 04:10 PM

    • State changed from “new” to “hold”
    • Tag set to distutils_is_a_mess, setup

    I have tried making pg_config_exe a lazy property, but as you have noticed, build_ext is invoked even if only install is 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 PostgresConfig constructor to the pg_config_helper.query("libdir") below.

    I don't see a way to detect build_ext has 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.

  • Adrian Klaver

    Adrian Klaver January 9th, 2013 @ 04:45 PM

    Thanks for looking at it. I am still groping my way through distutils to see if there is a solution.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

WARNING: the informations in this tracker are archived. Please submit new tickets or comments to the new tracker.


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.

Shared Ticket Bins

Referenced by

Pages