Repository: pypa/virtualenv

Issue:
virtualenv fails to create virtual environment from Homebrew-installed Python 3.4.3
When I try to create a virtual environment with Python 3.4.3, `virtualenv` errors out:

```
Running virtualenv with interpreter /usr/local/bin/python3.4
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/virtualenv.py", line 23, in <module>
    import subprocess
  File "/usr/local/Cellar/python3/3.4.3_2/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 405, in <module>
    import _posixsubprocess
ImportError: dlopen(/usr/local/lib/python2.7/site-packages/_posixsubprocess.so, 2): Symbol not found: _PyString_AsString
  Referenced from: /usr/local/lib/python2.7/site-packages/_posixsubprocess.so
  Expected in: flat namespace
 in /usr/local/lib/python2.7/site-packages/_posixsubprocess.so
```

I've found another reference to the exact same error [on StackOverflow](http://stackoverflow.com/questions/29911318/error-when-setting-up-virtualenv-with-python-3), with the only answer suggesting to add the `--no-site-packages` argument. Looking through `virtualenv -h`, I see that not only is it deprecated, it doesn't change the setting, as its functionality is currently the default. Predictably, this does not help.



Discussion:
What's your PYTHONPATH look like? It looks like the problem is that your python 3 is loading modules built for python 2.7.

Seems similar to https://github.com/pypa/virtualenv/issues/705

Doing `echo $PYTHONPATH` resulted in a blank line.


Resolving patch:
diff --git a/virtualenv.py b/virtualenv.py
--- a/virtualenv.py
+++ b/virtualenv.py
@@ -1,9 +1,22 @@
 #!/usr/bin/env python
 """Create a "virtual" Python installation"""
 
-import base64
-import sys
 import os
+import sys
+
+# If we are running in a new interpreter to create a virtualenv,
+# we do NOT want paths from our existing location interfering with anything,
+# So we remove this file's directory from sys.path - most likely to be
+# the previous interpreter's site-packages. Solves #705, #763, #779
+if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
+    del_paths = []
+    for path in sys.path:
+        if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path):
+            del_paths.append(path)
+    for path in del_paths:
+        sys.path.remove(path)
+
+import base64
 import codecs
 import optparse
 import re
@@ -17,6 +30,11 @@
 import subprocess
 from distutils.util import strtobool
 
+try:
+    import ConfigParser
+except ImportError:
+    import configparser as ConfigParser
+
 __version__ = "13.2.0.dev0"
 virtualenv_version = __version__  # legacy
 
@@ -30,10 +48,6 @@
 except NameError:
     basestring = str
 
-try:
-    import ConfigParser
-except ImportError:
-    import configparser as ConfigParser
 
 join = os.path.join
 py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1])
@@ -947,45 +961,34 @@ def change_prefix(filename, dst_prefix):
 
 def copy_required_modules(dst_prefix, symlink):
     import imp
-    # If we are running under -p, we need to remove the current
-    # directory from sys.path temporarily here, so that we
-    # definitely get the modules from the site directory of
-    # the interpreter we are running under, not the one
-    # virtualenv.py is installed under (which might lead to py2/py3
-    # incompatibility issues)
-    _prev_sys_path = sys.path
-    if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
-        sys.path = sys.path[1:]
-    try:
-        for modname in REQUIRED_MODULES:
-            if modname in sys.builtin_module_names:
-                logger.info("Ignoring built-in bootstrap module: %s" % modname)
-                continue
-            try:
-                f, filename, _ = imp.find_module(modname)
-            except ImportError:
-                logger.info("Cannot import bootstrap module: %s" % modname)
+
+    for modname in REQUIRED_MODULES:
+        if modname in sys.builtin_module_names:
+            logger.info("Ignoring built-in bootstrap module: %s" % modname)
+            continue
+        try:
+            f, filename, _ = imp.find_module(modname)
+        except ImportError:
+            logger.info("Cannot import bootstrap module: %s" % modname)
+        else:
+            if f is not None:
+                f.close()
+            # special-case custom readline.so on OS X, but not for pypy:
+            if modname == 'readline' and sys.platform == 'darwin' and not (
+                    is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
+                dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
+            elif modname == 'readline' and sys.platform == 'win32':
+                # special-case for Windows, where readline is not a
+                # standard module, though it may have been installed in
+                # site-packages by a third-party package
+                pass
             else:
-                if f is not None:
-                    f.close()
-                # special-case custom readline.so on OS X, but not for pypy:
-                if modname == 'readline' and sys.platform == 'darwin' and not (
-                        is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))):
-                    dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so')
-                elif modname == 'readline' and sys.platform == 'win32':
-                    # special-case for Windows, where readline is not a
-                    # standard module, though it may have been installed in
-                    # site-packages by a third-party package
-                    pass
-                else:
-                    dst_filename = change_prefix(filename, dst_prefix)
-                copyfile(filename, dst_filename, symlink)
-                if filename.endswith('.pyc'):
-                    pyfile = filename[:-1]
-                    if os.path.exists(pyfile):
-                        copyfile(pyfile, dst_filename[:-1], symlink)
-    finally:
-        sys.path = _prev_sys_path
+                dst_filename = change_prefix(filename, dst_prefix)
+            copyfile(filename, dst_filename, symlink)
+            if filename.endswith('.pyc'):
+                pyfile = filename[:-1]
+                if os.path.exists(pyfile):
+                    copyfile(pyfile, dst_filename[:-1], symlink)
 
 
 def subst_path(prefix_path, prefix, home_dir):


Test patch: