Python バッチ処理する「subprocess.run()」

'21/09/12更新:
 本記事では、Pythonスクリプトの処理の途中で、Windwosのコマンドプロンプトや、Linuxのターミナルでシェルを実行したい場合の雛形コードを載せました。コマンド処理の完了を待つ場合、「subprocess.run()」を使用します。標準出力やエラーを戻り値として取得できます。

# シェルコマンドを実行する
cmd_list = ['echo', basename]
cmd = ' '.join(cmd_list)
result = subprocess.run(
    cmd, # 実行コマンド
    encoding='utf-8', #文字列として取得する場合(指定しないとバイト列)
    shell=True,
    stdout=PIPE, # 標準出力
    stderr=PIPE, # 標準エラー出力
    #text=True
)
print('1. 終了ステータス', result.returncode)
print('2. 標準出力', result.stdout)
print('3. 標準エラー出力', result.stderr)

 一方、コマンド処理を待たずにPython処理を続行したい場合はPopenを使用します。

 subprocess.Popen() 

 この場合、サブプロセス(子プロセス)として残ります。終了させるには後のPythonコードで終了させるか、手動で終了させる必要があります。この場合の使用例は次のリンク先を参照下さい→https://hk29.hatenablog.jp/entry/2021/08/14/191947

そうでもなく、単にシェルコマンドを実行させたいだけの場合は、次のようにします。

 subprocess.call(cmd, shell=True) 

 

■本プログラム
私が良く使うファイル操作もいくつか追加した雛形コードです。

import glob
import os
import subprocess
from subprocess import PIPE
import shutil


# ディレクトリを作成する関数
# この時、すでに存在すれば一旦ディレクトリごと削除してから作成する
def create_dir_func(path):
    # ディレクトリがあれば削除する(サブディレクトリやファイルも削除する)
    if os.path.exists(path):
        shutil.rmtree(path)
    # ディレクトリを作成する
    os.mkdir(path)


def main():
    # ディレクトリを作成する関数を実行
    create_dir_func(mypath)

    for file_path in file_list:
        # 拡張子なしファイル名を取得する
        basename = os.path.splitext(os.path.basename(file_path))[0]
        
        # シェルコマンドを実行する
        cmd_list = ['echo', basename]
        cmd = ' '.join(cmd_list)
        result = subprocess.run(
            cmd, # 実行コマンド
            encoding='utf-8', #文字列として取得する場合(指定しないとバイト列)
            shell=True,
            stdout=PIPE, # 標準出力
            stderr=PIPE, # 標準エラー出力
            #text=True
        )
        print('1. 終了ステータス', result.returncode)
        print('2. 標準出力', result.stdout)
        print('3. 標準エラー出力', result.stderr)
        
        # ファイルをコピーする
        new_file_path = mypath + '/' + basename + '.csv'
        shutil.copy(file_path, new_file_path)
        #shutil.move(file_path, new_file_path) # コピーでなく移動したい場合
        
    # フォルダを圧縮する
    # 引数は、順に(圧縮後のファイル名, 圧縮フォーマット, 圧縮したいフォルダパス)
    shutil.make_archive('csv_files', 'zip', root_dir = mypath)
    #shutil.unpack_archive('csv_files.zip', extract_dir = './aaa') #解凍したい場合
    

if __name__ == '__main__':
    # ターゲットディレクトリパス
    mypath = 'new_dir'
    
    # 特定の拡張子のファイルをリストで取得する
    file_list = glob.glob('data_dir/*.csv')
    
    main()

以上

<広告>