Changing PYTHONHOME causes ImportError: No module named site
<p>I am trying to deploy a Flask web app via mod_wsgi on Apache. I cannot use the default Python environment because it was compiled with UCS-2 Unicode instead of UCS-4, and I cannot recompile it for this one case. Thus, a virtual environment. Virtual environments would have been used anyway, but that error means that I can't get away with using the default Python install and just adding the virtual environment's modules to the <code>PYTHONPATH</code>, which otherwise would have let me avoid the current problem entirely by accident.</p>

<p>I found the <a href="http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPythonHome.html" rel="nofollow">documentation for <code>mod_wsgi</code> to change which Python executable to use</a>. However, when attempting to do so, the server fails to work properly. <code>/var/log/httpd/error_log</code> rapidly floods with the line <code>ImportError: No module named site</code>.</p>

<p>I have checked every similar question I can find here and elsewhere, and not yet had success. Experimentation has shown that as far as I can tell, the problem occurs when changing PYTHONHOME without activating a virtual environment - and the way the automated deployment works (via Fabric), as far as I can tell I can't activate a virtual environment.</p>

<hr>

<h2>Apache config</h2>

<p>My current <code>httpd.conf</code> for the app:</p>

<pre><code>WSGIPythonPath /path/to/dir/containing/wsgi/file/and/app:/path/to/virtualenv/lib:/path/to/virtualenv/lib/site-packages

WSGIPythonHome /path/to/virtualenv

WSGISocketPrefix /var/run/wsgi

User user

Group group

&lt;VirtualHost *&gt;

    ServerName servername.generic.com

    DocumentRoot /path/to/dir/containing/wsgi/file/and/app/static_dev/

    WSGIDaemonProcess appname user=user group=group threads=2

    WSGIScriptAlias / /path/to/dir/containing/wsgi/file/and/app/app.wsgi

    &lt;Directory /path/to/dir/containing/wsgi/file/and/app&gt;
        WSGIProcessGroup appname
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</code></pre>

<hr>

<h2>Data I've found from failed attempts</h2>

<p>I know that the error is not in my <code>app.wsgi</code>, because when I added the line <code>raise Exception('tried to open the file')</code> at the very top to check that, the existing <code>ImportError</code> kept happening instead of that new <code>Exception</code>.</p>

<p>I have confirmed via <code>ldd</code> that my version of <code>mod_wsgi</code> is for Python 2.7.</p>

<p>I have tried setting <code>WSGIPythonHome /path/to/virtualenv/bin/</code> and <code>WSGIPythonHome /path/to/virtualenv/bin/python</code>, with the same result as the current state.</p>

<p>I have tried omitting the <code>WSGIPythonHome</code> directive, in which case it loads the <code>app.wsgi</code> as it should, but breaks on a later import as described at the top (the reason I can't just do that).</p>

<p>I have tried omitting the <code>WSGIPythonPath</code> directive and leaving it up to <code>app.wsgi</code> to add things to the PYTHONPATH, with the same result as the current state.</p>

<p>I have tried putting the path-setting as an argument to <code>WSGIDaemonProcess</code> instead of as the <code>WSGIPythonPath</code> directive, with the same result as the current state.</p>

<p>I have confirmed that there is a <code>site.py</code> in <code>/path/to/virtualenv/lib</code>.</p>

<p>I have confirmed that no other non-app-specific Apache <code>.conf</code> files being used (default settings, automatic module loads, etc) contain the string "WSGI", so I don't think there's any conflicts here.</p>

<p>If I activate the virtual environment from the command line I can import <code>site</code> without an error, just for the sake of testing that it does in fact exist in the environment. However, this is insufficient because it needs to start smoothly from a single call to <code>sudo systemctl start httpd.service</code> due to the deployment tools in use, and that seems to not care about the venv of the current shell session.</p>

<p>If, from a default state, I <code>export PYTHONHOME=/path/to/virtualenv</code>, attempting to open the Python REPL exits immediately with <code>ImportError: No module named site</code>.</p>

<p>If I activate the virtual environment and then set <code>PYTHONHOME</code>, I get the same import error.</p>

<p>If I activate the virtual environment and don't touch <code>PYTHONHOME</code>, <code>echo $PYTHONHOME</code> outputs a blank line, and the Python REPL works fine. In the Python REPL while in the virtualenv:</p>

<pre><code>(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.prefix
'/path/to/virtualenv'
&gt;&gt;&gt; sys.exec_prefix
'/path/to/virtualenv'
</code></pre>

<p>Even though setting <code>PYTHONHOME</code> to the same value didn't work.</p>

<p>If I try <code>export PYTHONHOME=:/path/to/virtualenv</code> or <code>export PYTHONHOME=/path/to/virtualenv:</code>, explicitly setting only one of <code>prefix</code> and <code>exec_prefix</code>, it fails with the same import error in either case.</p>

<p>If I activate the virtual environment and set <code>PYTHONHOME</code> in one of those latter two ways, the unset one appears to default to <code>/</code> rather than to the usual default value, but the Python REPL runs fine:</p>

<pre><code># Setting only exec_prefix
(virtualenv)-bash-4.2$ export PYTHONHOME=:/path/to/virtualenv
(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.prefix
'/'
&gt;&gt;&gt; sys.exec_prefix
'/path/to/virtualenv'
&gt;&gt;&gt; quit()
# Setting only prefix
(.virtualenv)-bash-4.2$ export PYTHONHOME=/path/to/virtualenv:
(.virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.prefix
'/path/to/virtualenv'
&gt;&gt;&gt; sys.exec_prefix
'/'
</code></pre>

<p>Unfortunately, since the deployment script doesn't care what environment is activated, that doesn't solve it. Trying to set <code>WSGIPythonHome</code> in such a fashion makes no difference whatsoever.</p>

<p>I have noticed one further thing: The Python in the virtualenv is <strong>2.7.8</strong>. The Python run outside the virtualenv (<code>usr/bin/python</code>) is <strong>2.7.5</strong>. I do not know - would this affect the setting of <code>PYTHONHOME</code> somehow? I would hope not - since that seems to defeat the entire purpose of using <code>WSGIPythonHome</code> to run a virtualenv as compared to just setting <code>sys.path</code> inside the <code>app.wsgi</code> file, the ability to start from a different executable - but I cannot rule it out, clueless as I am.</p>

<p>The 2.7.8 Python in <code>/path/to/virtualenv/bin/python</code> has a <code>sys.real_prefix</code> of <code>/network-mounted-drive/sw/python/python-2.7.8</code>.</p>

<p>I changed the deployment to build from <code>/network-mounted-drive/sw/python/python-2.7.5</code>, then did more tests. Results as follows:</p>

<p>Attempting to start httpd gives the same import error as before.</p>

<p>Setting PYTHONHOME to the location of the virtual environment, then running python:</p>

<pre><code>-bash-4.2$ echo $PYTHONHOME
/path/to/virtualenv
-bash-4.2$ python
ImportError: No module named site
</code></pre>

<p>Setting PYTHONHOME to the location of the virtual environment, then explicitly running the virtual environment's python binary (activating the virtual environment and then running <code>python</code> gives the same result):</p>

<pre><code># In the directory just above the virtualenv
-bash-4.2$ ./virtualenv/bin/python
Python 2.7.5 (default, Mar 14 2016, 14:13:09)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys.prefix
'/path/to/virtualenv'
&gt;&gt;&gt; sys.exec_prefix
'/path/to/virtualenv'
&gt;&gt;&gt; sys.real_prefix
'/network-mounted-drive/sw/python/python-2.7.5
</code></pre>

<hr>

<p>Does anyone have any idea?</p>

<p>Resolution found: The issue seems to have been in trying to use a virtual environment built from something other than the local python install on the system.</p>

<p>Solved by pushing the problem of "local python install on the deployment VM doesn't have pip installed" up the chain to someone with the permissions required to install pip, since no attempted workarounds via networked python installs worked.</p>

<p>The issue of actually using a virtual environment chained from a Python install on a network drive for mod_wsgi may be insoluble, or at least I couldn't figure it out in a reasonable amount of time relative to the bureaucratic solution.</p>

python centos mod-wsgi fabric importerror