代码之家  ›  专栏  ›  技术社区  ›  Matt Joiner

当没有从现有终端调用时,是否阻止控制台应用程序关闭?

  •  8
  • Matt Joiner  · 技术社区  · 15 年前

    在这种问题上有许多变体。但是,我特别想找到一种方法来防止在没有从终端(或者在Windows上调用的其他控制台)调用Python中的控制台应用程序时关闭它。出现这种情况的一个例子是双击 .py 来自Windows资源管理器的文件。

    通常,我使用类似于以下代码片段的代码,但即使从现有终端调用应用程序,它也会产生不好的操作副作用:

    def press_any_key():
        if os.name == "nt":
            os.system("pause")
    atexit.register(press_any_key)
    

    它还假设所有Windows用户都在从Windows“shell”调用应用程序,并且只有Windows用户才能从现有终端以外的位置执行程序。

    是否有一种(最好是跨平台)方法来检测我的应用程序是否已从终端调用,和/或是否需要为当前运行的实例提供“按任意键…”功能?请注意,采用批处理、bash或任何其他“包装过程”解决方法都是非常不可取的。

    更新0

    使用 Alex Martelli's 回答如下,我已经生成了这个函数:

    def register_pause_before_closing_console():
        import atexit, os
        if os.name == 'nt':
            from win32api import GetConsoleTitle
            if not GetConsoleTitle().startswith(os.environ["COMSPEC"]):
                atexit.register(lambda: os.system("pause"))
    
    if __name__ == '__main__':
        register_pause_before_closing_console()
    

    如果出现其他合适的答案,我将为其他平台和桌面环境附加更多代码。

    更新1

    在使用的脉络中 pywin32 我已经生产了 accepted answer

    def _current_process_owns_console():
        #import os, win32api
        #return not win32api.GetConsoleTitle().startswith(os.environ["COMSPEC"])
    
        import win32console, win32process
        conswnd = win32console.GetConsoleWindow()
        wndpid = win32process.GetWindowThreadProcessId(conswnd)[1]
        curpid = win32process.GetCurrentProcessId()
        return curpid == wndpid
    
    def register_pause_before_closing_console():
        import atexit, os, pdb
        if os.name == 'nt':
            if _current_process_owns_console():
                atexit.register(lambda: os.system("pause"))
    
    if __name__ == '__main__':
        register_pause_before_closing_console()
    
    2 回复  |  直到 15 年前
        1
  •  6
  •   gz.    8 年前

    code to detect when the console needs to be prevented from closing

    def owns_console():
        wnd = GetConsoleWindow()
        if wnd is None:
            return False
        return GetCurrentProcessId() == GetWindowThreadProcessId(wnd)
    

        2
  •  3
  •   Alex Martelli    15 年前

    sys.stdin.isatty() sys.stdout sys.stderr

    .py .pyw win32api.SetConsoleCtrlHandler CTRL_CLOSE_EVENT win32api.GetConsoleTitle try except False True