kill()后从子进程中检索一个值

时间:2015-10-04 04:42:55

标签: python subprocess popen sys

这是一个奇怪的项目,我试图使用子流程来跟踪我按下的键数来衡量我的工作效率。

目前,我使用Amazon Dash按钮启动子流程,然后在第二次按下时终止该流程。

def start_keylogger():
    global process
    process = subprocess.Popen(["sudo", "python", "test.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def stop_keylogger():
    os.killpg(process.pid, signal.SIGUSR1)
    process.wait()
    key_press_count = process.stdout.read()
    return key_press_count

从那里我的键盘记录器还没有充实,但我想我想用sys.exit()exit()来返回按键次数。

def exit_and_return_counter():
    sys.stdout.write(current_keypress_counter)
    exit()

if __name__ == '__main__':
    signal.signal(signal.SIGUSR1, exit_and_return_counter)
    try:
        while 1:
           main_loop()
    except KeyboardInterrupt:
        sys.exit()

最初我尝试使用process.returncode,但它只返回1,我假设成功退出代码。我不能使用stdout, stderr = process.communicate(),除非我想在按下第二个亚马逊按钮后保持键盘记录器不久。

3 个答案:

答案 0 :(得分:1)

简单地跑 process.wait()之后的os.killpg(process.pid, signal.SIGUSR1)。这等待进程结束并返回状态代码。就在你刚刚杀死它之前,它不会长时间阻挡。捕获USR1信号并使用sys.exit更改从孩子返回的代码应该可以正常工作。

即使在孩子被杀之后,您也应该能够使用process.stdout.read()读取stdout,因为为进程间通信创建的管道将至少与Popen对象process存在一样长

答案 1 :(得分:1)

虽然不是一个优雅的答案,但使用process.send_signal(signal.SIGUSR1)工作(如@ cg909所述)。在stop方法中我们有:

def stop_keylogger():
    process.send_signal(signal.SIGUSR1)
    process.wait()
    return process.stderr.read()

然后在键盘记录器中处理我们的信号:

def exit_and_return_counter(*args):
    sys.stdout.write('%s'%counter)
    exit()

if __name__ == '__main__':
    signal.signal(signal.SIGUSR1, exit_and_return_counter)
    try:
        while 1:
            main_loop()
    except KeyboardInterrupt:
        sys.exit()

答案 2 :(得分:0)

您可以在终端中使用SIGINT信号( Ctrl + C )来通知进程打印统计信息并退出。您可以使用SIGINT异常处理程序处理KeyboardInterrupt

#!/usr/bin/env python
#file: keylogger.py
import random
import time

counter = 0

def mainloop()
    global counter
    while True:
        counter += 1
        time.sleep(random.random())

if __name__ == '__main__':
    try:
        mainloop()
    except KeyboardInterrupt: # on SIGINT
        print(counter)

这是相应的控制器:

#!/usr/bin/env python3
import os
import signal
from subprocess import Popen, PIPE, DEVNULL

process = None

def start_keylogger():
    global process
    stop_keylogger(expect_process_running=False)
    process = Popen(["python", "-m", "keylogger"], stdout=PIPE, stderr=DEVNULL,
                    preexec_fn=os.setpgrp)

def stop_keylogger(expect_process_running=True):
    global process
    if process is not None and process.poll() is None:
        os.killpg(process.pid, signal.SIGINT)
        counter = int(process.communicate()[0])
        process = None
        return counter
    if expect_process_running:
        raise RuntimeError('keylogger is not running')

您可以通过按 Ctrl + C 在终端中运行SIGINT(用于测试/调试)来模拟发送keylogger.py。< / p>

preexec_fn=os.setpgrp创建一个单独的流程组。 os.killpg()向其发送信号。如果keylogger.py在不需要preexec_fn=os.setpgrp的情况下不生成自己的子流程,则只需拨打process.send_signal(signal.SIGINT)而不是os.killpg()即可。

考虑importing the keylogger module and using its functions instead of using subprocess