5

How can you tell whether python has been started with the -i flag?

According to the docs, you can check the PYTHONINSPECT variable in os.environ, which is the equivalent of -i. But apparently it doesn't work the same way.

Works:

$ PYTHONINSPECT=1 python -c 'import os; print os.environ["PYTHONINSPECT"]'

Doesn't work:

$ python -i -c 'import os; print os.environ["PYTHONINSPECT"]'

The reason I ask is because I have a script that calls sys.exit(-1) if certain conditions fail. This is good, but sometimes I want to manually debug it using -i. I suppose I can just learn to use "PYTHONINSPECT=1 python" instead of "python -i", but it would be nice if there were a universal way of doing this.

ʞɔıu
  • 47,148
  • 35
  • 106
  • 149

3 Answers3

3

How to set inspect mode programmatically

The answer from the link @Jweede provided is imprecise. It should be:

import os
os.environ['PYTHONINSPECT'] = '1'

How to retrieve whether interactive/inspect flags are set

Just another variant of @Brian's answer:

import os
from ctypes import POINTER, c_int, cast, pythonapi

def in_interactive_inspect_mode():
    """Whether '-i' option is present or PYTHONINSPECT is not empty."""
    if os.environ.get('PYTHONINSPECT'): return True
    iflag_ptr = cast(pythonapi.Py_InteractiveFlag, POINTER(c_int))
    #NOTE: in Python 2.6+ ctypes.pythonapi.Py_InspectFlag > 0
    #      when PYTHONINSPECT set or '-i' is present 
    return iflag_ptr.contents.value != 0

See the Python's main.c.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
2

I took a look at the source, and although the variable set when -i is provided is stored in Py_InteractiveFlag, it doesn't look like it gets exposed to python.

However, if you don't mind getting your hands a bit dirty with some low-level ctypes inspecting, I think you can get at the value by:

import ctypes, os

def interactive_inspect_mode():
    flagPtr = ctypes.cast(ctypes.pythonapi.Py_InteractiveFlag, 
                         ctypes.POINTER(ctypes.c_int))
    return flagPtr.contents.value > 0 or bool(os.environ.get("PYTHONINSPECT",False))

[Edit] fix typo and also check PYTHONINSPECT (which doesn't set the variable), as pointed out in comments.

Brian
  • 116,865
  • 28
  • 107
  • 112
  • `InteractiveFlag` ignores PYTHONINSPECT environment variable. – jfs Mar 12 '09 at 21:34
  • Thanks, I've fixed the typo, and added a check for the environment variable as well. – Brian Mar 12 '09 at 22:00
  • 1
    It is worth mentioning Py_InspectFlag (Python 2.6+). It is > 0 if '-i' is present or PYTHONINSPECT is set and not empty. Add link to the source http://svn.python.org/view/python/trunk/Modules/main.c?view=markup – jfs Mar 12 '09 at 22:17
  • Interesting - I was looking at the 2.5 source, which lacks this flag, but it looks like a more appropriate flag for later versions. It does miss the case where PYTHONINSPECT is set by python code after python has started however, so the env check may still be needed. – Brian Mar 12 '09 at 22:29
  • `os.environ` check is definitely required. There are `Py_InspectFlag = 0;` lines in main.c – jfs Mar 12 '09 at 22:38
0

No need for ctypes these days. This is available through sys.flags.inspect. (The Python 2 documentation indicates this was added in Python 2.6.)

There is also sys.flags.interactive, but this is not set when using the environment variable PYTHONINSPECT.

Tested on Python 3.10.12:

$ python -c "import sys; print(sys.flags.inspect, sys.flags.interactive)"
0 0

$ python -i -c "import sys; print(sys.flags.inspect, sys.flags.interactive)"
1 1

$ PYTHONINSPECT=1 python -c "import sys; print(sys.flags.inspect, sys.flags.interactive)"
1 0
otaithleigh
  • 11
  • 1
  • 2