13

Just as the title says. I want to write a script that behaves differently depending on whether it's running inside a console window or in IDLE. Is there an object that exists only when running in IDLE that I can check for? An environment variable?

I'm using Python 2.6.5 and 2.7 on Windows.

Edit:

The answers given so far work. But I'm looking for an official way to do this, or one that doesn't look like a hack. If someone comes up with one, I'll accept that as the answer. Otherwise, in a few days, I'll accept the earliest answer.

martineau
  • 119,623
  • 25
  • 170
  • 301
KeJi
  • 288
  • 2
  • 10

5 Answers5

15

I would prefer to do:

import sys
print('Running IDLE' if 'idlelib.run' in sys.modules else 'Out of IDLE')
Tony Veijalainen
  • 5,447
  • 23
  • 31
  • This does not work with Python 2.7.2. Try to search for 'idlelib.__main__' instead – Dhara May 29 '12 at 10:49
  • It works in 2.7.3, just rerun it in IDLE command line and CMD in windowsXP and by running the script in both. – Tony Veijalainen May 30 '12 at 12:18
  • If you save this as a script and open it in IDLE from the right-click context menu, then it doesn't work. If you open IDLE first then open the script, it works. The method I suggested works in both cases [This is a known "feature" of IDLE: in the first case, it opens both the script and the interpreter in the same process] – Dhara May 30 '12 at 13:00
  • 1
    `'idlelib.__main__'` doesn't work in (at least) python3.6. Just looking for `'idlelib'` seems the most reliable. – Arne Aug 22 '19 at 07:22
  • @Dhara: Your method does not work in Python 3.8.8 (and this answer does). – martineau May 17 '21 at 13:41
6

Google found me this forum post from 2003. With Python 3.1 (for win32) and the version of IDLE it comes with, len(sys.modules) os 47 in the command line but 122 in the IDLE shell.

But why do you need to care anyway? Tkinter code has some annoyances when run with IDLE (since the latter uses tkinter itself), but otherwise I think I'm safe to assume you shouldn't have to care.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • Hmm... sys.modules is a dict, with some keys that start with "idlelib.", so I could check for that. But it sounds like a hack, so I'd like to avoid it. They can even have different lengths (2.6.5:149, 2.7:152). – KeJi Aug 07 '10 at 18:43
  • Well, I guess this isn't possible without ugly hacks. That's the reason I ask why you think you need to... –  Aug 07 '10 at 18:58
  • 2
    With the console, I want to be able to clear the screen, move the cursor, add color, use msvcrt.getch, etc. Most of those don't seem to work in IDLE, and some will even fail silently, so instead of letting that happen, I'd rather make it check if it's running in IDLE or not. – KeJi Aug 07 '10 at 19:02
  • Well, I fear you're out of luck here. Unless you want to hack around, that is. Sorry. –  Aug 07 '10 at 19:18
  • 1
    One might care because [multiprocessing examples tend to run poorly in IDLE](http://stackoverflow.com/a/21199005/2738262). – Damian Yerrick Mar 28 '15 at 15:05
  • getch does not work in IDLE, that would be a good time to know whether IDLE is being ran or not. – Lukas Kalinski Mar 23 '18 at 10:56
5

I suggest packing all the code in one function (Python 3):

def RunningIntoPythonIDLE():

    import idlelib.PyShell

    def frames(frame = sys._getframe()):
        _frame = frame
        while _frame :
            yield _frame
            _frame = _frame.f_back

    return idlelib.PyShell.main.__code__ in [frame.f_code for frame in frames()]

So tkinter apps can do its check:

if not RunningIntoPythonIDLE():
    root.mainloop()
3

I'm a touch late, but since IDLE replaces the standard streams with custom objects (and that is documented), those can be checked to determine whether a script is running in IDLE:

import sys

def in_idle():
    try:
        return sys.stdin.__module__.startswith('idlelib')
    except AttributeError:
        return True
Noah
  • 1,329
  • 11
  • 21
  • If "it is happening in IDLE", `sys.stdin.__module__.startswith('idlelib')` returns `True` and if it is not, then there is an `AttributeError`, so in the `except` clause `False` should be returned, right? – khaz May 08 '23 at 15:58
1

My suggestion is to get list of all running frames and check if main Idle method would be in there.

def frames(frame = sys._getframe()):
    _frame = frame
    while _frame :
        yield _frame
        _frame = _frame.f_back
import idlelib.PyShell
print(idlelib.PyShell.main.func_code in [frame.f_code for frame in frames()])

the frames function generates frames running at moment of its declaration, so you can check if idle were here.

Odomontois
  • 15,918
  • 2
  • 36
  • 71
  • It works, but if it wasn't opened with a script, then it returns False. But there are other idlelib objects in it like . (tried with 2.6) – KeJi Aug 07 '10 at 21:25