Repository: ipython/ipython

Issue:
ipython startup error in terminal 
I did a clean install of anaconda python on a Mac, and option 6.2.1 is (among things) installed. I type python (gives me python 3.6.5) on a terminal, and I get the expected response  of an ipython terminal. I exit and type conda update ipython, and it goes to 6.3.1. Now when I type ipython at the terminal it gives me a string of errors, for example:
```
 Traceback (most recent call last):
  File "/Users/gkv/anaconda3/bin/ipython", line 11, in <module>
    sys.exit(start_ipython())
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/__init__.py", line 125, in start_ipython
    return launch_new_instance(argv=argv, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/application.py", line 657, in launch_instance
    app.initialize(argv)
  File "<decorator-gen-112>", line 2, in initialize
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/ipapp.py", line 317, in initialize
    self.init_shell()
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/ipapp.py", line 333, in init_shell
    ipython_dir=self.ipython_dir, user_ns=self.user_ns)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/configurable.py", line 412, in instance
    inst = cls(*args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/interactiveshell.py", line 430, in __init__
    super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 483, in __init__
    self.init_virtualenv()
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 740, in init_virtualenv
    if p_exe_up2 and os.path.samefile(p_exe_up2, p_venv):
  File "/Users/gkv/anaconda3/lib/python3.6/genericpath.py", line 97, in samefile
    s2 = os.stat(f2)
FileNotFoundError: [Errno 2] No such file or directory: ''
```

However, if I type jupyter console, then all is well. If I revert back to ipython6.2.1 then all is well again when I type ipython.  I guess this is some problem with an inconsistency in the anaconda distribution rather than ipython itself, but I thought I would report it in case you know the solution. Thanks. 


Discussion:
I think that would happen if the `VIRTUAL_ENV` environment variable is set to a path that doesn't exist. Could that be the case?
@takluyver I haven't knowingly set any virtual environment variable. Furthermore,  when I revert back to 6.2.1 everything works fine, from the same terminal pane, so presumably I have the same environment variables set in the two cases. 
We changed a bit how the virtualenv detection works in 6.3. Can you try running `echo $VIRTUAL_ENV` in the terminal you're launching IPython from?
I've done this and get a blank response:
~:->> echo $VIRTUAL_ENV

~:->>
Same response both  before and after updating to ipython 6.3.1. 
That's odd. It shouldn't be reaching that code at all if `VIRTUAL_ENV` is not set, because it checks:

https://github.com/ipython/ipython/blob/01bd59ec7c184171df0cb0d933c5672e8c20b67e/IPython/core/interactiveshell.py#L731-L733

Can you try inspecting the same variable inside Python:

```python
import os
print(os.environ['VIRTUAL_ENV']
```
I also get a blank response to this. Specifically, you can see my responses to ipython and python below, when ipython is 6.3.1

```
~:->> ipython
Traceback (most recent call last):
  File "/Users/gkv/anaconda3/bin/ipython", line 11, in <module>
    sys.exit(start_ipython())
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/__init__.py", line 125, in start_ipython
    return launch_new_instance(argv=argv, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/application.py", line 657, in launch_instance
    app.initialize(argv)
  File "<decorator-gen-112>", line 2, in initialize
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/application.py", line 87, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/ipapp.py", line 317, in initialize
    self.init_shell()
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/ipapp.py", line 333, in init_shell
    ipython_dir=self.ipython_dir, user_ns=self.user_ns)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/traitlets/config/configurable.py", line 412, in instance
    inst = cls(*args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/terminal/interactiveshell.py", line 430, in __init__
    super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 483, in __init__
    self.init_virtualenv()
  File "/Users/gkv/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 740, in init_virtualenv
    if p_exe_up2 and os.path.samefile(p_exe_up2, p_venv):
  File "/Users/gkv/anaconda3/lib/python3.6/genericpath.py", line 97, in samefile
    s2 = os.stat(f2)
FileNotFoundError: [Errno 2] No such file or directory: ''

If you suspect this is an IPython bug, please report it at:
    https://github.com/ipython/ipython/issues
or send an email to the mailing list at ipython-dev@python.org

You can print a more detailed traceback right now with "%tb", or use "%debug"
to interactively debug it.

Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
    c.Application.verbose_crash=True

~:->> python
Python 3.6.5 |Anaconda custom (64-bit)| (default, Mar 29 2018, 13:14:23) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print(os.environ['VIRTUAL_ENV'])

>>> 
```
Aha, if it prints an empty line rather than raising `KeyError`, then it must be set to an empty string. We should defend against that.
I see through a glass darkly....  and yes, you are quite right. I had set  VIRTUAL_ENV="",  for no good reason that I can think of now. When I remove that then ipython 6.3.1 works as expected. So it is a slightly obscure use case, although nonetheless one that shouldn't throw an error. 
I'm hoping to work on this issue. Here are some clarifying questions that would help me better understand the situation:
- Am I right to say that `init_virtualenv` exists to support the case when the user is in a virtualenv but is running an ipython executable outside of the virtualenv? Isn't this usage quite pathological because it defeats the purpose of being in a virtualenv? If so, why do we try to support it by helping the user access site packages within the virtualenv? 
- In this specific problem, one could argue that the behavior we observe is intended. The user did set VIRTUAL_ENV = "", and that indeed is an invalid file/directory. What's the rationale for wanting to fix this?
- My proposed fixed would be: 
```
 if 'VIRTUAL_ENV' not in os.environ or os.environ['VIRTUAL_ENV'] == '': 
     # Not in a virtualenv 
     return 
```
 Is this what we had in mind? @takluyver 

Resolving patch:
diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -737,7 +737,7 @@ def init_virtualenv(self):
 
         # executable path should end like /bin/python or \\scripts\\python.exe
         p_exe_up2 = os.path.dirname(os.path.dirname(p))
-        if p_exe_up2 and os.path.samefile(p_exe_up2, p_venv):
+        if p_exe_up2 and os.path.exists(p_venv) and os.path.samefile(p_exe_up2, p_venv):
             # Our exe is inside the virtualenv, don't need to do anything.
             return
 


Test patch: