python subprocess使用_python Subprocess的使用

进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。

subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

subprocess模块是python从2.4版本开始引入的模块。主要用来取代一些旧的模块方法,如os.system、os.spawn*、os.popen*、commands.*等。subprocess通过子进程来执行外部指令,并通过input/output/error管道,获取子进程的执行的返回信息。

调用subprocess的推荐方法是对于它可以处理的所有使用场景都使用run()函数。run()函数是在Python 3.5中添加的,如果在老版本中使用,需要下载并扩展。

pip install subprocess.run

使用方法

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False,env=None)

运行args描述的命令。等待命令完成,然后返回一个CompletedProcess实例。class subprocess.CompletedProcess表示从run()返回的值,表示已完成的进程。

完整的函数形式很大程度上与Popen构造函数相同 —— 除timeout、input和check之外,该函数的所有参数都传递给Popen接口。

参数

args

args是所有调用所必需的,应该为一个字符串或一个程序参数序列list。通常倾向提供参数序列,因为它允许这个模块来处理任何所需的转义和引用参数(例如,允许文件名中的空格)。如果传递单个字符串,shell必须为True(见下文),否则字符串必须简单地命名要执行的程序而不指定任何参数。

stdin、stdout和stderr

stdin、stdout和stderr分别指定执行程序的标准输入,标准输出和标准错误文件句柄。有效值有PIPE、DEVNULL,一个存在的文件描述器(正整数),一个存在的文件对象和None。PIPE表示应该为子进程创建新的管道。DEVNULL表示将使用特殊文件os.devnull。使用默认设置None,则不会发生重定向;子进程的文件句柄将从父进程继承。此外,stderr可以是STDOUT,表示来自子进程的标准错误数据应该捕获到与stdout相同的文件句柄中。

shell

如果shell是True,则将通过shell执行指定的命令。如果你使用Python主要是由于它能提供大多数系统shell不能提供的增强的控制流,并且仍然希望方便地访问其他shell功能,如shell管道、文件名通配符、环境变量扩展和扩展〜到用户的主目录,这会很有用。

>>> from subprocess import run

>>> print run('uname -r')

3.7.0-7-generic

>>> print run('uname -r').stdout

3.7.0-7-generic

>>> run('uname -a').status

0

>>> print run('rm not_existing_directory').stderr

rm: cannot remove `not_existing_directory': No such file or directory

>>> print run('ls -la', 'wc -l')

14

>>> print run('ls -la', 'wc -l', 'wc -c')

3

>>> run('ls -la', 'wc -l', 'wc -c')

ls -la | wc -l | wc -c

>>> print run('ls -la').stdout.lines

['total 20',

'drwxrwxr-x 3 user user 4096 Dec 20 22:55 .',

'drwxrwxr-x 5 user user 4096 Dec 20 22:57 ..',

'drwxrwxr-x 2 user user 4096 Dec 20 22:37 dir',

'-rw-rw-r-- 1 user user 0 Dec 20 22:52 file']

只是执行一些指令的时候通过subprocess.run 即可。可以指定stdout,stderr,cwd(代码工作路径),env(环境变量)

def get_path_env(kaldi=DIR.KALDI): # 在kaldi内部 注意添加环境变量

old_path = os.environ['PATH']

ivectorbin_dir = os.path.join(kaldi, 'src', 'ivectorbin')

bin_dir = os.path.join(kaldi, 'src', 'bin')

new_path = "{}:{}:{}".format(ivectorbin_dir, bin_dir, old_path)

return {"PATH": new_path}

env = get_path_env() ,env = {'PATH':$PATH} 这种形式。

有时候需要将一个进程的输入当做另外一个进程的输出,用到subprocess.Popen

import subprocess

child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)

child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout, stdout=subprocess.PIPE)

out = child2.communicate()

def transform(xvector_scp_fp, test_scp_fp, test_ark_fp, sre16_major_dir=None, sre_combined_dir=None):

"""

Transform xvector from dimension of 600 to vecotr of dimension 150.

The actual dimensions are decided by `transform.mat`.

Params:

`sre16_major_dir`: The official `xvectors_sre16_major` directory, which contains `mean.vec`;

`sre_combined_dir`: The official `xvectors_sre_combined` directory, which contains `transform.mat`;

`xvector_scp_fp`: scp file path for xvectors to be transformed;

`test_scp_fp`: location of the destination file path

NOTE: Here we generate scp file and ark file, instead of only ark file. The reason is to accommandate

the case where a lot of xvectors are invloved. Since xvector scp file is

created by default, we don't have to consider when there is not xvector scp file.

"""

sre16_major_dir = sre16_major_dir or path.join(DIR.CONSTDIR, 'xvectors_sre16_major')

sre_combined_dir = sre_combined_dir or path.join(DIR.CONSTDIR, 'xvectors_sre_combined')

env = get_path_env() # 执行路径对应第69行,run_faiss.sh

subtract_cmd = ['ivector-subtract-global-mean']

mean_vec_dir = path.join(sre16_major_dir, 'mean.vec')

subtract_cmd.append(mean_vec_dir)

subtract_cmd.append("scp:{}".format(xvector_scp_fp))

subtract_cmd.append("ark:-")

p1 = subprocess.Popen(subtract_cmd, stdout=subprocess.PIPE, env=env, stderr=subprocess.DEVNULL) # p1.stdout

trans_cmd = ['transform-vec']

trans_mat_fp = path.join(sre_combined_dir, 'transform.mat')

trans_cmd.append(trans_mat_fp)

trans_cmd.append("ark:-")

trans_cmd.append("ark:-")

p2 = subprocess.Popen(trans_cmd, stdin=p1.stdout, stdout=subprocess.PIPE, env=env, stderr=subprocess.DEVNULL)

norm_cmd = ['ivector-normalize-length']

norm_cmd.append('ark:-')

dest = "ark,scp:{},{}".format(test_ark_fp, test_scp_fp)

norm_cmd.append(dest)

p3 = subprocess.Popen(norm_cmd, stdin=p2.stdout, stdout=subprocess.PIPE, env=env,stderr=subprocess.PIPE)

# wait for p3 to execute

rv = p3.communicate()[0]

if p3.returncode != 0:

raise XvectorTransformationError(p3.stdout, p3.stderr)

p3.communicate()

p3.returncode != 0

rv.returncode != 0

class PldaScoreError(Exception):

"""plda score error"""

def cmd_err(err_cls): # 添加报警错误,plda_scores_error

def outer(fn):

def inner(*args, **kwargs):

rv = fn(*args, **kwargs)

if rv.returncode != 0:

err_msg = rv.stdout + rv.stderr # 报警错误信息显示,

if type(err_msg) is bytes:

err_msg = err_msg.decode()

print(err_msg)

raise err_cls

else:

return rv

return inner

return outer

@cmd_err(PldaScoreError)

def score(enroll_ark_fp, test_ark_fp, trials_fp, score_fp, log_dir=None, sre16_major_dir=default_sre16, cwd=DIR.KALDIROOT): # 不需要 num_utts.ark 文件

"""

Params:

`sre16_major_dir`: the directory where `plda_adapt` locates

`enroll_ark_fp`: enroll ark file path

`test_ark_fp`: test ark file path

`trials_fp`: trials file path

`score_fp`: the file path for the generated score file

"""

log_dir = log_dir or (score_fp + ".log")

cmd = ['utils/run.pl']

cmd.append(log_dir)

cmd.append("ivector-plda-scoring")

cmd.append("--normalize-length=true")

plda_fp = path.join(sre16_major_dir, 'plda_adapt')

plda_sub_cmd = "ivector-copy-plda --smoothing=0.0 {} - |".format(plda_fp)

cmd.append(plda_sub_cmd)

cmd.append("ark:{}".format(enroll_ark_fp))

cmd.append("ark:{}".format(test_ark_fp))

cmd.append(trials_fp)

cmd.append(score_fp)

env = get_path_env()

return subprocess.run(cmd, cwd=cwd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # cwd 设定子进程当前工作目录,env 用于指定子进程环境变量,env

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SubprocessPython标准库中用于创建新进程的模块。它允许你启动一个新的进程,并与该进程进行交互,包括向其输入数据、从其输出数据等。 其中,communicate()方法是Subprocess模块中最常用的方法之一,它用于与子进程进行交互。当你使用Subprocess启动一个新的进程时,你可以在communicate()方法中向该进程输入数据,并在该进程完成后从该进程读取输出数据。 具体来说,communicate()方法会向进程的标准输入发送数据,并等待该进程完成后读取其标准输出和标准错误输出。该方法会返回一个元组,其中第一个元素表示标准输出,第二个元素表示标准错误输出。 例如,下面的代码展示了如何使用Subprocess模块来启动一个新的进程,并将数据传递给该进程: ``` import subprocess # 启动一个新的进程 process = subprocess.Popen(['python', 'my_script.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 向进程发送数据 process.stdin.write('input data'.encode()) # 等待进程完成并读取其输出数据 output, error = process.communicate() # 打印输出结果 print(output.decode()) ``` 在上面的代码中,我们启动了一个新的进程,并将一个字符串作为输入数据发送给该进程。然后,我们使用communicate()方法等待该进程完成,并读取其标准输出和标准错误输出。最后,我们将输出结果打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值