Close Python IDLE shell without prompt

前端 未结 1 1004
栀梦
栀梦 2020-12-20 06:03

I am working on a script (script A), that needs to open a new Python IDLE shell, automatically run another script (script B) in it and then close it. The following code is w

相关标签:
1条回答
  • 2020-12-20 06:59

    Instead of monkeypatching or modifying the IDLE source code to make your program skip the prompt to exit I'd recommend you create a subclass of PyShell that overrides the close method how you want it to work:

    import idlelib.PyShell
    class PyShell_NoExitPrompt(idlelib.PyShell.PyShell):
        def close(self):
            "Extend EditorWindow.close(), does not prompt to exit"
    ##        if self.executing:
    ##            response = tkMessageBox.askokcancel(
    ##                "Kill?",
    ##                "Your program is still running!\n Do you want to kill it?",
    ##                default="ok",
    ##                parent=self.text)
    ##            if response is False:
    ##                return "cancel"
            self.stop_readline()
            self.canceled = True
            self.closing = True
            return idlelib.PyShell.EditorWindow.close(self)
    

    The original issue with this was that then using idlelib.PyShell.main would not use your subclass, you can in fact create a copy of the function - without modifying the original - by using the FunctionType constructor that will use your modified class:

    import functools
    from types import FunctionType
    
    def copy_function(f, namespace_override):
        """creates a copy of a function (code, signature, defaults) with a modified global scope"""
        namespace = dict(f.__globals__)
        namespace.update(namespace_override)
        new_f = FunctionType(f.__code__, namespace, f.__name__, f.__defaults__, f.__closure__)
        return functools.update_wrapper(f, new_f)
    

    Then you can run your extra IDLE shell like this:

    import sys
    #there is also a way to prevent the need to override sys.argv but that isn't as concerning to me.
    sys.argv = ['','-n','-t','My New Shell','-c','execfile("VarLoader.py")']
    hacked_main = copy_function(idlelib.PyShell.main,
                                {"PyShell":PyShell_NoExitPrompt})
    
    hacked_main()
    

    Now you can leave IDLE the way it is and have your program work the way you want it too. (it is also compatible with other versions of python!)

    0 讨论(0)
提交回复
热议问题