tags:

views:

164

answers:

3

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.

+1  A: 

This specifies how to programatically switch your script to interactive mode.

Jweede
I want to tell whether it is already in interactive mode, not set it
ʞɔıu
whoops. Sorry, the last part of your question threw me off. :-)
Jweede
+1  A: 

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.

J.F. Sebastian
+1  A: 

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
s/ types/ ctypes/
J.F. Sebastian
`InteractiveFlag` ignores PYTHONINSPECT environment variable.
J.F. Sebastian
Thanks, I've fixed the typo, and added a check for the environment variable as well.
Brian
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
J.F. Sebastian
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
`os.environ` check is definitely required. There are `Py_InspectFlag = 0;` lines in main.c
J.F. Sebastian