防止控制台应用程序在未从现有终端调用时关闭? [英] Prevent a console app from closing when not invoked from an existing terminal?

查看:140
本文介绍了防止控制台应用程序在未从现有终端调用时关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这种问题有很多变种。然而,我特别是在一个方法后,防止控制台应用程序在Python中关闭时,它不是从终端(或其他控制台,因为它可能在Windows上调用)。这可能发生的一个例子是双击从Windows资源管理器中的 .py 文件。

There are many variants on this kind of question. However I am specifically after a way to prevent a console application in Python from closing when it is not invoked from a terminal (or other console, as it may be called on Windows). An example where this could occur is double clicking a .py file from the Windows explorer.

像下面的代码片段,但它具有操作的不幸副作用,即使从现有终端调用应用程序:

Typically I use something like the following code snippet, but it has the unfortunate side effect of operating even if the application is invoked from an existing terminal:

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

这也假设所有Windows用户都是从Windowsshell调用应用程序,只有Windows用户才能执行程序

It's also making the assumption that all Windows users are invoking the application from the Windows "shell", and that only Windows users can execute the program from a location other than an existing terminal.

是否有(最好是跨平台)方式来检测我的应用程序是否已从终端调用,和/或是否必须为当前运行的实例提供按任意键...功能吗?请注意,使用批处理,bash或任何其他封装进程解决方法是非常不受欢迎的。

Is there a (preferably cross platform) way to detect if my application has been invoked from a terminal, and/or whether it is necessary to provide a "press any key..." functionality for the currently running instance? Note that resorting to batch, bash or any other "wrapper process" workarounds are highly undesirable.

使用 Alex Martelli的 answer下面,我已经产生了这个函数:

Using Alex Martelli's answer below, I've produced this function:

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()

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

If other suitable answers arise, I'll append more code for other platforms and desktop environments.

使用 pywin32 ,我已经生成功能,这改进了上述,使用接受的答案。注释掉的代码是源自Update0的替代实现。如果使用pywin32不是一个选项,请按照接受答案。暂停或getch()尝试。

In the vein of using pywin32, I've produced this function, which improves on the one above, using the accepted answer. The commented out code is an alternative implementation as originating in Update0. If using pywin32 is not an option, follow the link in the accepted answer. Pause or getch() to taste.

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()


推荐答案

首先,试图阻止你从聪明的黑客。有一个独立的快捷方式设计为从资源管理器执行略有不同的事情(如持有控制台打开)从脚本中使用从命令行是完全适当的。正如亚历克斯已经指出,这不是一个问题,在尼克斯,正确的做法是总是完全退出或用户会抱怨。

First, an attempt to disuade you from clever hacks. It's perfectly appropriate to have a seperate shortcut designed to be run from Explorer that does slightly different things (like holding the console open) from the script to be used from the commandline. As Alex has already pointed out, this is not an issue on nix, and the right thing to do there is always exit cleanly or your users will complain.

如果你仍然想要一个解决方法,这里是代码,以检测控制台何时需要阻止关闭这是相当干净。需要Windows 2000或更高版本,逻辑包含在此函数中:

If you still want a workaround, here's code to detect when the console needs to be prevented from closing that's reasonably clean. Requires Windows 2000 or later, the logic is contained in this function:

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

基本上,它获取拥有Python正在使用的控制台的进程的PID,以及我们的进程的PID。如果他们是相同的,那么当我们退出控制台将会消失,所以它需要保持打开。如果它们不同,或者没有连接控制台,Python应该正常退出。

Basically, it gets the PIDs of the process that owns the console Python is using, and of our process. If they are the same, then when we exit the console will go away, so it needs to be held open. If they are different, or if there's no console attached, Python should exit normally.

这篇关于防止控制台应用程序在未从现有终端调用时关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆