【发布时间】:2017-04-17 11:46:15
【问题描述】:
我可以用
中断我在 Windows 中的子进程import ctypes
ctypes.windll.kernel32.GenerateConsoleCtrlEvent(1, _proc.pid)
但前提是我通过正常的 Python 进程运行它。
当我使用 Python C API(代码如下)通过单独的启动程序运行相同的代码时,上面的代码没有任何效果。
我应该以某种方式更改我的启动器以便能够中断子进程吗?
#include <Python.h>
#include <windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
LPWSTR *argv;
int argc;
argv = CommandLineToArgvW(GetCommandLine(), &argc);
if (argv == NULL)
{
MessageBox(NULL, L"Unable to parse command line", L"Error", MB_OK);
return 10;
}
Py_SetProgramName(argv[0]);
Py_Initialize();
PySys_SetArgvEx(argc, argv, 0);
PyObject *py_main, *py_dict;
py_main = PyImport_AddModule("__main__");
py_dict = PyModule_GetDict(py_main);
PyObject* result = PyRun_String(
"from runpy import run_module\n"
"run_module('thonny')\n",
Py_file_input,
py_dict,
py_dict
);
int code;
if (!result) {
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
PyObject* valueAsString = PyObject_Str(pvalue);
wchar_t* error_msg = PyUnicode_AsWideCharString(valueAsString, NULL);
MessageBox(0, error_msg, L"Thonny startup error", MB_OK | MB_ICONERROR);
code = -1;
}
else {
code = 1;
}
Py_Finalize();
return code;
}
编辑:原来pythonw.exe 也有同样的问题。
【问题讨论】:
-
除非目标
pid实际上是一个进程组 ID,如文档所述,否则GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)的行为是未定义的。实际上,它的作用就像pid为 0,即它将事件广播到连接到控制台的每个进程。你不想要那个。它可能会杀死附加到控制台的父进程。 -
至于您的启动器,它根本没有连接到控制台,所以我不明白您为什么认为
GenerateConsoleCtrlEvent会起作用。 -
最好的办法是使用真正的 IPC,例如命名事件对象。 (当然,我不知道如何在 Python 中做到这一点。)
-
@eryksun ,我正在使用
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP创建进程,因此它适用于普通 Python。任何想法,如何将启动器附加到控制台? -
@eryksun , 启动器是一个 GUI 进程,它使用 python.exe 来运行后台任务。当我通过 Eclipse Pydev 运行我的模块时,没有看到控制台窗口,但我可以中断后端。当我通过启动器运行它时,后端会弹出控制台窗口,但我无法中断它。
标签: python windows subprocess interrupt