How to tell if I'm being run from a shell or a module

D

dg.google.groups

Hi all,

Is there any standard way to tell if the user is running from a module
or from an interactive shell like IDLE or IPython? The best I've come
up with so far is for a function to look at
getouterframes(currentframe())[1][1] (the filename in the frame record
of the frame that called the function), and check if it exists or not
with os.path.exists. IPython gives '(ipython console)' and IDLE gives
'pyshell#0' whereas running from a module gives its filename. This
seems a bit hacky. Any better ideas?
 
C

Chris

Hi all,

Is there any standard way to tell if the user is running from a module
or from an interactive shell like IDLE or IPython? The best I've come
up with so far is for a function to look at
getouterframes(currentframe())[1][1] (the filename in the frame record
of the frame that called the function), and check if it exists or not
with os.path.exists. IPython gives '(ipython console)' and IDLE gives
'pyshell#0' whereas running from a module gives its filename. This
seems a bit hacky. Any better ideas?

If you're just trying to prevent some actions from happening if
something loads your script as a module just put the 'action items'
under an if like:
if __name__ == '__main__':
do_the_cool_stuff()

All your functions inside the file will remain in-tact but it won't
execute anything.
 
D

dg.google.groups

Thanks for the replies, but it's not what I meant. What I want to be
able to determine is whether or not the user is running from an
interactive shell (like IPython or IDLE). Checking if
__name__=='__main__' checks if the current module is the one being
run, but suppose you have two modules A and B, with the function f
defined in module B that should print 'Interactive' or 'Module' say.
The module A just consists of: import B; B.f(). Now whenever f is
called, __name__ will not be '__main__' for it. Someone using IDLE
could write import B then B.f() too. The question is: is there a way
for f to determine if someone was using an interactive shell to call
it or if it was being called some other way. The way I came up with
works in these limited cases but won't work in a more general
situation (but perhaps there is no way for it to know in the more
general situation).

Dan
 
G

Gabriel Genellina

Thanks for the replies, but it's not what I meant. What I want to be
able to determine is whether or not the user is running from an
interactive shell (like IPython or IDLE). Checking if
__name__=='__main__' checks if the current module is the one being
run, but suppose you have two modules A and B, with the function f
defined in module B that should print 'Interactive' or 'Module' say.
The module A just consists of: import B; B.f(). Now whenever f is
called, __name__ will not be '__main__' for it. Someone using IDLE
could write import B then B.f() too. The question is: is there a way
for f to determine if someone was using an interactive shell to call
it or if it was being called some other way. The way I came up with
works in these limited cases but won't work in a more general
situation (but perhaps there is no way for it to know in the more
general situation).

It depends on what you mean by "an interactive shell"? If you start your
script with:
python -i whatever.py
is it an interactive shell or not?

I tried these two criteria:
a) See if the __main__ module has a __file__ attribute.
b) See if sys.stdin is a real tty

These are the results I got on Windows for several configurations:

<test.py>
import sys
print "__main__ has __file__", hasattr(sys.modules['__main__'], '__file__')
import os
print "sys.stdin is a tty", hasattr(sys.stdin, "fileno") and
os.isatty(sys.stdin.fileno())
</test.py>

python test.py
__main__ has __file__ True
sys.stdin is a tty True

python -i test.py
__main__ has __file__ True
sys.stdin is a tty True

python test.py <nul >nul
__main__ has __file__ True
sys.stdin is a tty True

python test.py <emptyfile >nul
__main__ has __file__ True
sys.stdin is a tty False

pythonw.exe (the consoleless Python executable for Windows)
__main__ has __file__ True
sys.stdin is a tty False

IDLE
__main__ has __file__ False
sys.stdin is a tty False

pythonwin.exe
__main__ has __file__ False
sys.stdin is a tty False
 
D

dg.google.groups

It depends on what you mean by "an interactive shell"? If you start your
script with:
python -i whatever.py
is it an interactive shell or not?

I tried these two criteria:
a) See if the __main__ module has a __file__ attribute.
b) See if sys.stdin is a real tty

Right, so my idea of an 'interactive shell' seems to be a little ill
defined. Nonetheless, looking if the main module has a file attribute
looked to be a good idea until I tried it on IPython - returns True...

I think I'll do what I said in the first post, but add an option to
override the behaviour for less usual circumstances. Seems to be the
best compromise.

Dan
 
S

Sion Arrowsmith

Gabriel Genellina said:
a) See if the __main__ module has a __file__ attribute.
b) See if sys.stdin is a real tty

c) See if sys.argv[0] != ''

(Although this works for the command line interactive shell, I've a
suspicion it will fail with IDLE. But I don't have IDLE to hand to
check.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top