Detect where Python code is running (e.g., in Spyder interpreter vs. IDLE vs. cmd)

interpreter, python, spyder

Solution

Here is the solution I ended up using. After reading Markus's answer, I noticed that Spyder adds half a dozen or so environment variables to `os.environ` with names like `SPYDER_ENCODING`, `SPYDER_SHELL_ID`, etc. Detecting the presence of any of these seems relatively unambiguous, compared to detecting the absence of a variable with as generic a name as `'PYTHONSTARTUP'`. The code is simple, and works independently of Spyder's startup script (as far as I can tell):

if any('SPYDER' in name for name in os.environ)
    # use alternative
else:        
    # use getpass

Since the string is at the beginning of each environment variable name, you could also use `str.startswith`, but it's less flexible, and a little bit slower (I was curious):

>>> import timeit
>>> s = timeit.Timer("[name.startswith('SPYDER') for name in os.environ]", "import os")
>>> i = timeit.Timer("['SPYDER' in name for name in os.environ]", "import os")
>>> s.timeit()
16.18333065883474
>>> i.timeit()
6.156869294143846

The `sys.executable` method may or may not be useful depending on your installation. I have a couple WinPython installations and a separate Python 2.7 installation, so I was able to check the condition `sys.executable.find('WinPy') == -1` to detect a folder name in the path of the executable Spyder uses. Since the warning that shows in IDLE when you try to use `getpass` is less "loud" than it could be, in my opinion, I ended up also checking the condition `sys.executable.find('pythonw.exe') == -1` to make it slightly louder. Using `sys.executable` only, that method looks like:

if sys.executable.find('pythonw.exe') == sys.executable.find('WinPy') == -1:
    # use getpass
else:        
    # use alternative

But since I want this to work on other machines, and it's much more likely that another user would modify their WinPython installation folder name than that they would rename their IDLE executable, my final code uses `sys.executable` to detect IDLE and `os.environ` to detect Spyder, providing a "louder" warning in either case and keeping the code from breaking in the latter.

if any('SPYDER' in name for name in os.environ) \
   or 'pythonw.exe' in sys.executable:
    password = raw_input('WARNING: PASSWORD WILL BE SHOWN ON SCREEN\n\n' * 3
                         + 'Please enter your password: ')
else:        
    password = getpass.getpass("Please enter your password: ")

Problem

Is there a way in Python to detect, within a process, where that process is being executed? I have some code that includes the `getpass.getpass()` function, which is broken in Spyder, and it's annoying to go back and forth between the command line and the IDE all the time. It would be useful if I could add code like: ``` if not being run from Spyder: use getpass else: use alternative ```

Original source