您好,登錄后才能下訂單哦!
python 中Subprocess如何使用,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一、subprocess以及常用的封裝函數, 連接文檔,Popen不用wait用communicate
運行python的時候,我們都是在創建并運行一個進程。像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是所有調用所必需的,應該為一個字符串或一個程序參數序列list。通常傾向提供參數序列,因為它允許這個模塊來處理任何所需的轉義和引用參數(例如,允許文件名中的空格)。如果傳遞單個字符串,shell必須為True
(見下文),否則字符串必須簡單地命名要執行的程序而不指定任何參數。
stdin、stdout和stderr分別指定執行程序的標準輸入,標準輸出和標準錯誤文件句柄。有效值有PIPE
、DEVNULL
,一個存在的文件描述器(正整數),一個存在的文件對象和None。PIPE表示應該為子進程創建新的管道。DEVNULL表示將使用特殊文件os.devnull。使用默認設置None,則不會發生重定向;子進程的文件句柄將從父進程繼承。此外,stderr可以是STDOUT,表示來自子進程的標準錯誤數據應該捕獲到與stdout相同的文件句柄中。
如果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
關于python 中Subprocess如何使用問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。