Search code examples
python-2.7python-internals

exit() in python interpreter not working after overriding


I was working on my local python 2.7 interpreter to test some code logic. As, the command to close the interpreter is "exit()", I assigned a variable like,

exit = False

After trying out some calculations, when I wanted to quit out of my interpreter and gave

exit()

it threw following error,

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'bool' object is not callable

I know have overridden a system variable maybe but is it so easy to do that? And even If I did, when I tried to assign it to

exit = True

it keeps throwing me error like "bool object is not callable" So, what went wrong here?


Solution

  • I know have overridden a system variable maybe but is it so easy to do that?

    What you’ve done is shadowed a builtin name with a global name.1 That’s perfectly legal to do, and in fact sometimes it’s useful. For example:

    • Global namespaces are the same thing as module namespaces. If you weren’t allowed to define a shadowing exit in your module, sys wouldn’t be allowed to define sys.exit. And the same for io.open, codecs.open, and gzip.open. And numpy.min and pandas.apply. And so on.
    • One of the recommended ways to write dual-version code that works with both 2.7 and 3.x involves using future and putting 3.x-style zip, etc. into your globals.
    • Sometimes there are builtins that you don’t care about—they may even be undocumented, or documented as “legacy” functions that should have been deprecated back in 2.1 and removed in 2.4 but are still hanging around in 2.7. There’s no reason you should be forced to avoid those names. Especially if you’re writing code on a different interpreter or version that doesn’t even have those names, and then want to run it on one that does.
    • Various quick&dirty interactive-interpreter things that I don’t want to encourage, but we all do them occasionally.

    More generally, shadowing builtins with globals is the same thing as shadowing builtins, globals, or nonlocals with locals, so it would be pretty strange to ban one without banning the other.

    More generally still, Python is designed around the “consenting adults” idea. It doesn’t go out of its way to protect you from everything that might possibly be used to shoot yourself in the foot. There are a handful of things that are so rarely useful and so commonly cause trouble (like reassigning None) that it was worth adding a bit of code to prevent them, but for the most part, you’re free to do things even if it’s not always a good idea to do them.


    And even If I did, when I tried to assign it to

    exit = True
    

    it keeps throwing me error like "bool object is not callable" So, what went wrong here?

    That doesn’t undo what you did. It just means the builtin is now shadowed by a global with the value True, instead of one with the value False. And True is no more callable than False.

    If you want to undo the shadowing, just delete the shadowing global:

    del exit 
    

    1. Python has a few different meanings of “builtin” that don’t quite perfectly overlap. The exit function is not compiled as a builtin, and isn’t even part of the builtins module until it gets monkeypatched in by site, but it is accessed by builtin-namespace lookup, which is the meaning I’m talking about here.