Prevent a console app from closing when not invoked from an existing terminal?

一世执手 提交于 2019-11-30 09:17:11

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.

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)

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.

On Unix, sys.stdin.isatty() reliably tells you whether standard input is coming from a terminal-like device (or is otherwise redirected), and similarly for the same method on sys.stdout and sys.stderr -- so you can use those calls to determine whether the application is being executed interactively or in some non-interactive environment (such as a cron job). Exactly how you want to use them depends on what you want to do if (for example) both standard input and output are redirected to a non-terminal but standard error is going to a terminal -- consider each of the 8 possibilities, from all of them redirected to non-terminals to none of them, and decide what you want to do in each case.

On Windows the situation is different since executing a .py file (as opposed to a .pyw file) will create a new transient console (there's no exactly equivalent situation in Unix); I assume that's the case you want to deal with? (Or is it just about redirection of standard I/O streams to files, which is possible in Windows roughly just like in Unix?). I think the best approach in Windows might be to use win32api.SetConsoleCtrlHandler to set a handler for such events as CTRL_CLOSE_EVENT -- this way the handler should be invoked (in this case, when the console closes) if there is a console for the process, but not otherwise. Or, if all you care about is whether a console is there at all or not (and prefer to handle things your way otherwise), try calling win32api.GetConsoleTitle in the try leg of a try/except statement -- it will generate an exception (which you catch and respond to by setting a boolean variable of yours to False) if there's no console, and just work (in which case you set that boolean variable to True) if there is a console.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!