背景
我有一个通过 pyinstaller 编译成 Windows 可执行文件的 Python 3.5 控制台程序。
问题
- 当通过命令提示符执行时,我希望我的程序使用提供的任何参数(可能没有)运行。
- 当通过操作系统的 GUI 执行时(即通过在 Windows 的 Windows 资源管理器中双击 .exe 等),我希望我的程序提示用户输入。我还需要我的程序在退出前暂停,以便用户可以阅读输出。
我如何检测这些不同的场景?
约束
- 可执行文件必须能够在基本(即全新安装)Windows/RedHat 机器上运行。
- 编译 可执行文件必须是单个文件,并且不能依赖未打包在已编译可执行文件中的其他文件(pyinstaller 允许将文件打包在已编译可执行文件中)。
- 该程序可能依赖于第 3 方 python 包。
我尝试过的事情
sys.stdin.isatty()
https://stackoverflow.com/a/3818551/3508142
os.isatty(sys.stdout.fileno())
https://stackoverflow.com/a/6108504/3508142
这些在 Windows 上总是返回True
。搜索 StackOverflow/互联网:
How to determine if Python script was run via command line?
How can I check to see if a Python script was started interactively?
据我所知,如果用户启动了一个程序,无论它是从命令提示符还是 GUI 启动的,它都会交互式运行。我还考虑过检查父进程是
cmd.exe
还是explorer.exe
。但是,通过 Windows 运行命令启动程序将使explorer.exe
成为父进程。通过任务管理器启动程序将使任务管理器成为父进程。这些是我可以接受的极端情况,但显然我更喜欢更强大的解决方案。
最佳答案
计算连接到控制台的进程数
Windows API documentation for GetConsoleProcessList
import ctypes
# Load kernel32.dll
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
# Create an array to store the processes in. This doesn't actually need to
# be large enough to store the whole process list since GetConsoleProcessList()
# just returns the number of processes if the array is too small.
process_array = (ctypes.c_uint * 1)()
num_processes = kernel32.GetConsoleProcessList(process_array, 1)
# num_processes may be 1 if your compiled program doesn't have a launcher/wrapper.
if num_processes == 2:
input('Press ENTER to continue...')
关于python - 检测 python 程序是否通过 Windows GUI(双击)与命令提示符执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55172090/