Python

【Python】subprocessのコマンド実行出力をリアルタイムで取得する

この記事は約3分で読めます。

 

「 Python で外部コマンド実行」といえばまっさきに思いつくのは標準ライブラリの subprocess ですが、(私の理解が正しければ) subprocess を使うとコマンドが終了するまでその出力を Python でキャプチャできません。

 

関連記事:【Python】subprocessを使ってPython上からシェルコマンドを実行する

 

外部コマンドの出力をある程度リアルタイムに Python でキャプチャしたい場合は asyncio の subprocess 系の機能が有用です subprocess 。 具体的には asyncio.create_subprocess_exec() または asyncio.create_subprocess_shell() を使用します。

 

ただこの方法で stdout.readline()や stderr.readline()を使用すると、まれに whileループを抜けられないことがあります。 Python 公式ドキュメントにも次のような警告が書かれています。

Warning: Use the communicate()method rather than process.stdin.write()await process.stdout.read()or await process.stderr.read. This avoids deadlocks due to streams pausing reading or writing and blocking the child process.

参考にされる際はご注意ください。

 

次のコードは Python 公式の asyncio.create_subprocess_exec() のサンプルコード(こちら)を少し変更したものです

 

import sys
import subprocess


def get_lines(cmd):
    '''
    :param cmd: str 実行するコマンド.
    :rtype: generator
    :return: 標準出力 (行毎).
    '''
    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    while True:
        line = proc.stdout.readline()
        if line:
            yield line

        if not line and proc.poll() is not None:
            break


# コマンド
cmd = "python hello.py"

if __name__ == '__main__':
    for i in range(1):
      try:
        for line in get_lines(cmd=cmd):
            sys.stdout.write(line)
      except:
        pass

 

 

 


プログラミング・スクレイピングツール作成の相談を受け付けています!

クラウドワークス・ココナラ・MENTAなどでPython・SQL・GASなどのプログラミングに関する相談やツール作成などを承っております!

過去の案件事例:

  • Twitter・インスタグラムの自動化ツール作成
  • ウェブサイトのスクレイピングサポート
  • ダッシュボード・サイト作成
  • データエンジニア転職相談

これまでの案件例を見る

キャリア相談もお気軽に!文系学部卒からエンジニア・データサイエンティストへの転職経験をもとに、未経験者がどう進むべきかのアドバイスを提供します。


スポンサーリンク
/* プログラミング速報関連記事一覧表示 */
ミナピピンの研究室

コメント

タイトルとURLをコピーしました