ホーム DoRuby pythonでコマンドを扱う
pythonでコマンドを扱う
 

pythonでコマンドを扱う

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

pythonで標準入力と標準出力を扱います。

概要

pythonに慣れていて手軽に書けるので、他の言語でできることでもなるべくpythonでやりたいです。
ローカルマシンのプロセスをダンプする必要があったんですが、シェルスクリプトを書きたくなかったのでpythonで書きました。

コード

pythonのバージョンは3.6.1です。

import subprocess
import shlex
import os
from datetime import datetime

command = "ps alx"
log_file = os.path.dirname(os.path.abspath(__file__)) + "/process.log"

def main():
    buf_list = []
    buf_list.append(get_current_time())

    for i in readline_stdout():
        buf_list.append(i)

    write_file_to_log(buf_list)


# 現在時刻を取得
def get_current_time():
    current_time = datetime.now().strftime("%Y/%m/%d %H:%M:%S") + " ---------------------------------------------------------------------------------\n"
    return current_time


# 標準出力を一行ずつ受け取る
def readline_stdout():
    proc = subprocess.Popen(shlex.split(command), stdout = subprocess.PIPE, stderr = subprocess.PIPE)

    while True:
        line = proc.stdout.readline()
        yield line.decode("utf-8")

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


# ファイルに出力
def write_file_to_log(logs):
    file = open(log_file, 'a')
    file.writelines(logs)


if __name__ == "__main__":
    main()
# 実行結果の一部
2017/11/22 18:00:22 ---------------------------------------------------------------------------------
  UID   PID  PPID CPU PRI NI      VSZ    RSS WCHAN  STAT   TT       TIME COMMAND
    0     1     0   0  37  0  2536056   6748 -      Ss     ??    1:00.50 /sbin/launchd
    0    50     1   0  37  0  2550352  37604 -      Ss     ??    0:08.14 /usr/libexec/UserEventAgent (System)
    0    51     1   0   4  0  2515384   2672 -      Ss     ??    0:01.24 /usr/sbin/syslogd
    0    53     1   0  20  0   663372   1216 -      Ss     ??    0:00.56 /Applications/.esets/Contents/MacOS/esets_ctl
    0    54     1   0  20  0  2498064  10000 -      Ss     ??    0:01.52 /System/Library/PrivateFrameworks/Uninstall.framework/Resources/uninstalld
    0    55     1   0  37  0  2546936  12252 -      Ss     ??    0:02.51 /usr/libexec/kextd

ポイント

ポイントは2つです。
1. subprocessを使って標準入力と標準出力を扱う
2. shlexを使って文字列をシェルスタイルでパースする

subprocessを使って標準入力と標準出力を扱う

pythonでコマンドを扱う方法はcmdやos.system()など複数ありますが、subprocessを使うのがスタンダードなやり方っぽいです。

shlexを使う

今回のスクリプトを書いている中での最大の学びはshlexです。
たとえば、今回のコマンドは”ps alx”をそのまま渡してるんですが、shlex.split()を使わない場合は、[“ps”, “alx”]としてやる必要があります。
長いコマンドを処理したい時は面倒なので、shlexを使ってやると非常に便利です。

追記

shlex.splitを使わなくても、subprocess.Popemの引数にshell = True パラメーターを与えてやると"ps alx"でもうまくいきます。
shell = True パラメーターで処理をする利点は、"ps alx | grep hogeみたいにパイプ(“|”)を使ったコマンドが利用できるということです。
shlex.splitでパイプの入ったコマンドを利用しようとすると上手く処理できません。

追記その2

出力先ファイルのパス指定を修正しました。
cronで回したときに”process.log”だと実行時のパスが一致しないので、絶対パスを取得してやる必要がある。

記事を共有

最近人気な記事