Python Subprocess 模块 调用外部程序

应用场景

有一个 TeraFast 模块必须在 Python2.7 下运行。Windows 中 Tensorflow 不支持 Python2.7,故以外部调用的方式运行 TeraFast 模块。

Prototype 代码

先上可以运行的原型代码:

Parent Process: proto_parentprocess.py (running in Python 3)

import logging
import signal
import subprocess
import time
from os import kill

import numpy as np
from PIL import Image

''' Description
This script is used in junciton with proto_subprocess.py.
Parent: proto_parentprocess.py
Sub   : proto_subprocess.py

Parent create Sub using subprocess. Sub generates images and sends to PIPE. Parent gets images from PIPE and saves it.
This process is running in loop.
'''

logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(message)s')
logger = logging.getLogger()


def main():
    # Some settings
    cmd = ['/media/kent/DISK2/virtualenv_gallery/py27_tf1_10/bin/python', './proto_subprocess.py']
    final_shape = [151, 100, 3]
    sleep_time = 0.5  # in sec
    save_dir = './protoParentProcessOutput.jpeg'

    # Create the subprocess
    talkpipe = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
    logger.info('Subprocess PID: {}'.format(talkpipe.pid))
    try:
        while True:
            line = talkpipe.stdout.readline()
            line = line.decode('utf-8')
            line = line.strip()
            if line:
                line = line.replace('[', '')
                line = line.replace(']', '')
                np_output = np.fromstring(line, dtype=np.int, sep=' ')
                img = np.reshape(np_output, final_shape)
                img = img.astype('uint8')
                im = Image.fromarray(img)
                im.save(save_dir)
                logger.info('Image saved to {}'.format(save_dir))
            else:
                logger.warning('No data.')
            time.sleep(sleep_time)  # for stabilization purpose
    except KeyboardInterrupt:
        logger.warning('Killing child...')
        kill(talkpipe.pid, signal.SIGTERM)
    finally:
        kill(talkpipe.pid, signal.SIGTERM)
        logger.warning('Killed.')


if __name__ == '__main__':
    main()

Child Process: proto_subprocess.py (running in Python 2)

import sys
import time

import numpy as np
from PIL import Image

''' Description
This script is used in junciton with proto_parentprocess.py.
Parent: proto_parentprocess.py
Sub   : proto_subprocess.py

Parent create Sub using subprocess. Sub generates images and sends to PIPE. Parent gets images from PIPE and saves it.
This process is running in loop.
'''

# Generate some image
im = Image.open('/home/kent/Pictures/120611460-1.png')
np_im = np.array(im)  # uint8
np_im = np_im.astype(np.int)

'''
Because the patent process read the stdout data a line each time using talkpipe.stdout.readline(),
  we need to reshape the date to one line so that the parent process can get the whole data at each time.
Why using stdout.readline() not stdout.read()?
  I tested it and found that (probably) stdout.read() cannot read data interactively.
'''
write_out = np.reshape(np_im, [1, -1])

while True:
    np.savetxt(sys.stdout, write_out, fmt='%d')
    sys.stdout.flush()
    time.sleep(0.1)  # for stabilization purpose

关于 Subprocess 模块

Why subprocess:

Python的subprocess子进程和管道进行交互
其实在python中,和shell脚本,其他程序交互的方式有很多,比如:
os.system(cmd),os.system只是执行一个shell命令,不能输入、且无返回
os.open(cmd),可以交互,但是是一次性的,调用都少次都会创建和销毁多少次进程,性能太差
所以,建议用subprocess
(另外,这篇被转载的博客的原博主也有很多 Python 和 C++ 交互的例子)

How to use:

Python3学习(四十):python中的subprocess.Popen()使用
也是一篇被转载的博客,对 subprocess.Popen() 的参数和方法介绍了一下。

Python多进程(1)——subprocess与Popen()
和上一篇差不多,条理也很清晰。

关于 PIPE 传输数据的方式

思路1: 标准输出
上面我的例子里,用了标准的 sys.stdinsys.stdout,也就是 PIPE。
用这样的方式,必须注意一下传输的信息的编码类型。
Python 2 里会用 Unicode,直接打印传回的信息会显示类似 u’ … ‘。
Python 3 里会用 bytes,直接打印传回的信息会显示类似 b’ … '。

所以在解码传回的东西的时候,需要注意如何解码方式,我上面给的例子里是 line = line.decode('utf-8')

思路2:Pickle 序列化
我们可以考虑用 pickle 先把要传输的东西序列化,然后再用 PIPE 传。接收的时候再用 pickle 反序列化解码就可以了。我没有试过这种方式。不过有人问过这样的问题,说明应该是可以行得通的。

Transmitting a pickled object output between python scripts through a
subprocess.communicate

思路3:PyCommunicator
这是一个民间的 package (developped in Python 2, works only for Windows),是对subprocess 进行了 wrap。达到方便易用的目的。不过很久未更新了。我简单试了一下,Python 2 下可以用,不知道转成 Python 3 可不可以。有兴趣的值得一试。不过我试了一下 Python 3 调用 Python 2 程序,貌似未成功。有可能我的方式不对。

补充

Get realtime output from pythonsubprocess
这个问题和其中链接有更多讨论。

python调用外部子进程,通过管道实现异步标准输入和输出的交互

python 并发subprocess.Popen的坑

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: subprocess 模块Python 标准库中用于启动新的进程的模块。它可以用于执行外部命令、获取进程的输出、向进程发送输入、等待进程结束等操作。通过使用 subprocess 模块,可以在 Python 代码中更方便地控制外部程序,而不必编写额外的 shell 脚本。 ### 回答2: Pythonsubprocess模块是用于创建和管理新的子进程的模块。它提供了一个简单而灵活的方式来执行其他程序,并且可以与外部命令进行交互。 使用subprocess模块,我们可以启动一个新的进程,执行外部命令,并获取其输出。这对于需要执行其他语言编写的程序或者操作系统命令非常有用。通过subprocess模块,我们可以轻松地调用外部命令,并获取其标准输出、标准错误输出,以及执行的返回码。 subprocess模块提供了多种方法来创建并管理子进程,例如: - `subprocess.run()`:执行一个命令,等待其完成并返回运行结果。 - `subprocess.Popen()`:启动一个子进程,并返回一个Popen对象,可以通过该对象与子进程进行交互。 - `subprocess.call()`:执行一个命令,并等待其完成。与`subprocess.run()`类似,不过返回的是命令的返回码。 此外,subprocess模块还提供了一些方便的函数和常量,例如: - `subprocess.check_output()`:执行一个命令,并返回其标准输出。 - `subprocess.PIPE`:表示子进程的标准输入、输出和错误输出。 总而言之,subprocess模块是一个在Python调用和管理外部命令和程序的强大工具。无论是执行其他语言编写的程序,还是与操作系统命令进行交互,它都提供了便捷的功能和灵活的方法。 ### 回答3: Python subprocess模块提供了一个简便的接口,可以在Python程序中启动和控制新的子进程。它允许我们在代码中运行外部命令,并可以通过输入和输出进行交互。 使用subprocess模块,我们可以执行系统命令、启动其他可执行文件、调用命令行工具等。它提供了多种方法,可以满足不同情况下的需求。 subprocess模块中最常用的函数是`subprocess.run()`。使用该函数可以方便地执行外部命令,并等待其完成。我们可以指定命令和参数,还可以设置输入和输出的方式。 在使用`subprocess.run()`函数时,可以通过`capture_output`参数捕获命令的输出,通过`input`参数传递输入数据。这使得我们可以在Python程序中方便地处理子进程的输出和输入。 `subprocess`模块还提供了其他函数,例如`subprocess.call()`、`subprocess.check_output()`等,可以实现不同的功能。另外,还可以通过`subprocess.Popen()`类来更灵活地控制子进程。 总而言之,Python subprocess模块提供了一个简单、方便和强大的接口,可以在Python程序中执行和控制子进程。它使得我们可以轻松地与外部命令进行交互,并处理输入输出。因此,subprocess模块在编写Python脚本时非常实用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值