Как добиться желаемых результатов при использовании подпроцесса Popen.send_signal (CTRL_C_EVENT) в Windows? - PullRequest
5 голосов
/ 17 февраля 2011

В python 2.7 в Windows в соответствии с документацией вы можете отправить CTRL_C_EVENT (документация по Python 2.7 Popen.send_signal). Однако, когда я попробовал это, я не получил ожидаемое прерывание клавиатуры в подпроцессе.

Это пример кода для родительского процесса:

# FILE : parentProcess.py
import subprocess
import time
import signal

CREATE_NEW_PROCESS_GROUP = 512
process = subprocess.Popen(['python', '-u', 'childProcess.py'],
                       stdin=subprocess.PIPE,
                       stdout=subprocess.PIPE,
                       stderr=subprocess.STDOUT,
                       universal_newlines=True,
                       creationflags=CREATE_NEW_PROCESS_GROUP)
print "pid = ", process.pid
index = 0
maxLoops = 15
while index < maxLoops:
    index += 1
    # Send one message every 0.5 seconds
    time.sleep(0.5)
    # Send data to the subprocess
    process.stdin.write('Bar\n')
    # Read data from the subprocess
    temp = process.stdout.readline()
    print temp,
    if (index == 10):
        # Send Keyboard Interrupt
        process.send_signal(signal.CTRL_C_EVENT)

Это пример кода для дочернего процесса:

# FILE : childProcess.py
import sys

while True:
    try:
        # Get data from main process
        temp = sys.stdin.readline()
        # Write data out
        print 'Foo ' + temp,
    except KeyboardInterrupt:
        print "KeyboardInterrupt"

Если я запускаю файлparentProcess.py Я ожидаю получить «Foo Bar» десять раз, затем «KeyboardInterrupt», а затем «Foo Bar» 4 раза, но вместо этого я получаю «Foo Bar» 15 раз.

Есть ли способ получитьCTRL_C_EVENT, чтобы вести себя как прерывание клавиатуры так же, как SIGINT ведет себя в Linux?

После некоторого чтения я нашел некоторую информацию, которая, кажется, противоречит документации Python относительно CTRL_C_EVENT, в частности, она говорит, что

CTRL_C_EVENT 0 Генерирует сигнал CTRL + C.Этот сигнал не может быть сгенерирован для групп процессов

Следующий сайт предоставляет больше информации о флагах создания: Флаги создания процесса.

Ответы [ 2 ]

4 голосов
/ 07 мая 2012

Этот метод обработки сигналов подпроцессами работал для меня как в Linux, так и в Windows 2008, оба использовали Python 2.7.2, но вместо Ctrl-C он использует Ctrl-Break.См. Примечание о группах процессов и Ctrl-C в http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%29.aspx.

catcher.py:

import os
import signal
import sys
import time

def signal_handler(signal, frame):
  print 'catcher: signal %d received!' % signal
  raise Exception('catcher: i am done')

if hasattr(os.sys, 'winver'):
    signal.signal(signal.SIGBREAK, signal_handler)
else:
    signal.signal(signal.SIGTERM, signal_handler)

print 'catcher: started'
try:
    while(True):
        print 'catcher: sleeping...'
        time.sleep(1)
except Exception as ex:
    print ex
    sys.exit(0)

thrower.py:

import signal
import subprocess
import time
import os

args = [
    'python',
    'catcher.py',
    ]
print 'thrower: starting catcher'
if hasattr(os.sys, 'winver'):
    process = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
else:
    process = subprocess.Popen(args)

print 'thrower: waiting a couple of seconds for catcher to start...'
time.sleep(2)
print 'thrower: sending signal to catch'

if hasattr(os.sys, 'winver'):
    os.kill(process.pid, signal.CTRL_BREAK_EVENT)
else:
    process.send_signal(signal.SIGTERM)

print 'thrower: i am done'
0 голосов
/ 22 мая 2011

Попробуйте с

win32api.GenerateConsoleCtrlEvent(CTRL_C_EVENT, pgroupid)

или

win32api.GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pgroupid)

ссылки:

http://docs.activestate.com/activepython/2.5/pywin3/win32process_CREATE_NEW_PROCESS_GROUP.html

http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%29.aspx

прочитайте информацию о dwProcessGroupId, идентификатор группы должен совпадать с идентификатором процесса

...