zoukankan      html  css  js  c++  java
  • Python多进程

    1. subprocess

    homepage

    博客: 使用subprocess模块调用子进程并获取输出

    该模块主要用于调用子程序

    • multiprocess: 是同一个代码中通过多进程调用其他的模块(也是自己写的)
    • subprocess: 直接调用外部的二进制程序,而非代码模块

    1.1. Popen

    p.poll()  # 检查进程是否终止,如果终止返回returncode,否则返回None
    p.wait(timeout)  # 等待子进程终止(阻塞父进程)
    p.communicate(input,timeout)  # 和子进程交互,发送和读取数据(阻塞父进程)
    p.send_signal(singnal)  # 发送信号到子进程
    p.terminate()  # 停止子进程,也就是发送SIGTERM信号到子进程
    p.kill()  # 杀死子进程。发送SIGKILL信号到子进程
    

    创建Popen对象后,主程序不会自动等待子进程完成

    以上三个成员函数都可以用于等待子进程返回:while循环配合Popen.poll()、Popen.wait()、Popen.communicate()。由于后面二者都会阻塞父进程,所以无法实时获取子进程输出,而是等待子进程结束后一并输出所有打印信息。另外,Popen.wait()、Popen.communicate()分别将输出存放于管道内存,前者容易超出默认大小而导致死锁,因此不推荐使用。

    注意:p.communicate(stdin="xxx") 该函数会终止子程序(因为其是阻塞的,当父程序解除阻塞时,意味着子程序已经结束了)。所以,如果你的子程序是 while... 或者 for line in sys.stdin 时,你会发现子程序意外的结束了,而不是在循环中等待。

    1.1.1. 管理子进程(通信)

    Popen类具有三个与输入输出相关的属性:Popen.stdin , Popen.stdoutPopen.stderr ,分别对应子进程的标准输入/输出/错误。它们的值可以是PIPE、文件描述符(正整数)、文件对象或None

    • PIPE表示创建一个连接子进程的新管道,默认值None, 表示不做重定向。
    • 子进程的文件句柄可以从父进程中继承得到。
    • stderr 可以设置为 STDOUT ,表示将子进程的标准错误重定向到标准输出。
    child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
    child2 = subprocess.Popen(["wc"], stdin=child1.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    out = child2.communicate()
    

    其中,subprocess.PIPE为文本流提供一个缓存区,child1的stdout将文本输出到缓存区;随后child2的stdin从该PIPE读取文本,child2的输出文本也被存放在PIPE中,而标准错误信息则重定向到标准输出;最后,communicate()方法从PIPE中读取child2子进程的标准输出和标准错误。

    注意:subprocess.stdxxx 操作bytes字节,而 sys.stdin 则是string。

    sys.stdin

    Python的sys模块定义了标准输入/输出/错误:

    sys.stdin  # 标准输入
    sys.stdout # 标准输出
    sys.stderr # 标准错误信息
    

    以上三个对象类似于文件流,因此可以使用readline()和write()方法进行读写操作。也可以使用print(),等效于sys.stdout.write()。

    需要注意的是,除了直接向控制台打印输出外,标准输出/错误的打印存在缓存,为了实时输出打印信息,需要执行

    sys.stdout.flush()
    sys.stderr.flush()
    

    读取 sys.stdin 的方式:

    for line in sys.stdin:
        print(type(line))  # string
        ...
    
    示例

    前面提到,如果子程序只是调用一次,并获取其输出状态,可以使用 p.communicate(stdin, timeout) 结合 p.returncode 实现。

    但如果你的程序想实现类似 TCP-C/S 式的持续通信服务,这里提供一个Demo:

    父程序:

    proc = subprocess.Popen(command,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE)
                            # stderr=subprocess.STDOUT)
    
    # try:
    while proc.poll() is None:  # 持续输入
        str_input = input("Please Input a path: ")
        if str_input == "quit":
            break
    
        bytes_path = f"/home/brt/{str_input}.jpg
    ".encode()  # 注意这里需要
    换行符
        proc.stdin.write(bytes_path)  # 需要使用bytes
        proc.stdin.flush()
        # proc.communicate(stdin=str_input, timout=5)
    
        bytes_state = proc.stdout.readline()  # bytes
        if bytes_state == b"ok
    ":
            print("Well Done.")
    
    # except subprocess.TimeoutExpired:
    #     print("子程序Timout未响应...")
    #     break
    
    # if proc.poll() is None:  # communicate()超时时,子程序可能未退出
    #     proc.kill()
    

    子程序:

    for path_save in sys.stdin:  # 持续读取
        path_save = path_save.strip()  # 删除多余的换行符
        img = grabclipboard_byQt(cb)
        # sys.stderr.write(">>>", img)
        if img:
            save_clipboard_image(img, path_save)
            str_pipe = "ok"
        else:
            str_pipe = ""
    
        # 以下内容用于写入stdout管道,向父程序反馈
        # sys.stdout.write(str_pipe + "
    ")  # 必须添加换行符
        print(str_pipe)
        sys.stdout.flush()  # 及时清空缓存
    

    2. multiprocess

  • 相关阅读:
    JavaScript相关,this 的指向
    酷炫的渲染,CSS3动画!
    正襟危坐,聊一聊Web语义化
    本地存储的技术,localStorage、sessionStorage、cookie、session
    Express 系列(终章):MongoDB使数据持久化
    股票投资相关,成交量怎么看
    【日本語新聞選読】第5回:3月31日
    【1901日語听解2】第5回:3月30日
    【日語視聴説2】第5回:3月30日
    【日本語新聞編集】第4回:3月27日
  • 原文地址:https://www.cnblogs.com/brt2/p/13232368.html
Copyright © 2011-2022 走看看