【问题标题】:What is best practice to interact with subprocesses in python与python中的子进程交互的最佳实践是什么
【发布时间】:2021-04-19 14:38:51
【问题描述】:

我正在构建一个应用程序,旨在在另一个软件中进行批量处理数据。为了自动控制其他软件,我使用 pyautoit,一切正常,除了由外部软件引起的应用程序错误,有时会发生。

为了处理这些情况,我建立了一个看门狗:

  • 它使用子进程中的批量作业启动脚本

     process = subprocess.Popen(['python', job_script, src_path], stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE, shell=True)
    
  • 它使用winevt.EventLog模块监听系统事件

     EventLog.Subscribe('System', 'Event/System[Level<=2]', handle_event)
    
  • 如果发生错误,它会关闭一切并重新启动脚本。

好的,如果发生系统错误事件,则应该以某种方式处理此事件,以便通知 supprocess。然后,此通知应导致子流程中的以下操作:

在子流程中有一个对象控制着一切并不断收集 生成的数据。为了不必从头开始整个工作,在重新启动脚本后,必须使用 pickle 转储该对象(这不是问题!)

从子进程内部监听系统事件不起作用。调用 subprocess.Popen() 时会导致连续循环。

所以,我的问题是如何从子进程内部订阅系统事件,或在父进程和子进程之间进行通信 - 意味着发送一条消息,如“嘿,发生错误”,在子进程中侦听,然后创建转储?

在这种情况下不允许发布任何代码,我真的很抱歉。但我希望(并且实际上认为)我的描述应该是可以理解的。我的问题是关于使用哪个模块以最佳方式完成此任务?

如果有人能指出我正确的方向,我会很高兴...

兄弟, 麦克风

【问题讨论】:

    标签: python-3.x subprocess


    【解决方案1】:

    我相信最好的答案可能在这里:https://docs.python.org/3/library/subprocess.html#subprocess.Popen.stdin

    这些属性应该允许不同进程之间的适当通信相当容易,并且没有任何其他依赖关系。

    请注意,如果其他进程可能导致问题,Popen.communicate() 可能更适合。

    编辑以添加示例脚本:

    main.py

    from subprocess import *
    import sys
    
    def check_output(p):
        out = p.stdout.readline()
        return out
    
    def send_data(p, data):
        p.stdin.write(bytes(f'{data}\r\n', 'utf8'))  # auto newline
        p.stdin.flush()
    
    def initiate(p):
        #p.stdin.write(bytes('init\r\n', 'utf8'))  # function to send first communication
        #p.stdin.flush()
        send_data(p, 'init')
        return check_output(p)
    
    def test(p, data):
        send_data(p, data)
        return check_output(p)
    
    def main()
        exe_name = 'Doc2.py'
        p = Popen([sys.executable, exe_name], stdout=PIPE, stderr=STDOUT, stdin=PIPE)
        
        print(initiate(p))
        print(test(p, 'test'))
        print(test(p, 'test2'))  # testing responses
        print(test(p, 'test3'))
    
    if __name__ == '__main__':
        main()
    

    Doc2.py

    import sys, time, random
    
    def recv_data():
        return sys.stdin.readline()
    
    def send_data(data):
        print(data)
    
    while 1:
        d = recv_data()
        #print(f'd: {d}')
        if d.strip() == 'test':
            send_data('return')
        elif d.strip() == 'init':
            send_data('Acknowledge')
        else:
            send_data('Failed')
    

    这是我能想到的跨进程通信的最佳方法。还要确保所有请求和响应不包含换行符,否则代码会中断。

    【讨论】:

    • 谢谢,听起来不错))但是我怎样才能在子进程中获取通过标准输入发送的消息?意思是,在该进程中运行的脚本中?如何实现?
    • 我相信你应该使用 sys.stdin 从流中读取。我将测试一个程序并稍后给出一些示例代码。
    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 2022-01-03
    • 2020-11-03
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    相关资源
    最近更新 更多