这是一个奇怪的项目,我试图使用子流程来跟踪我按下的键数来衡量我的工作效率。
目前,我使用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()
,除非我想在按下第二个亚马逊按钮后保持键盘记录器不久。
答案 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
。