LinuxコマンドをPythonから扱う方法は多数ありますが、標準出力と標準エラー出力を構造的に扱える Popenクラス
を利用する方法が一番しっくりきます。
登場する関数
関数名 | 分類 | 型 |
---|---|---|
Popen().stdout.readline() | 標準出力 結果から1行だけ出力 | str |
Popen().stdout.readlines() | 標準出力 結果を配列で全て出力 | list[str] |
Popen().stderr.readline() | 標準エラー出力 結果から1行だけ出力 | str |
Popen().stderr.readlines() | 標準エラー出力 結果を配列で全て出力 | list[str] |
標準出力と標準エラー出力をPythonから扱う
output.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from subprocess import PIPE, Popen
def cmdline(command):
"""
コマンドを実行する。shell=Trueの場合シェル経由で実行する。
:param command: str
:return: Popen
"""
return Popen(
args=command,
stdout=PIPE,
stderr=PIPE,
shell=True
)
# 標準出力
print '標準出力:' + cmdline('date').stdout.readline()
# 標準エラー出力
print '標準エラー出力: ' + cmdline('echo 2015|xargs wc -l').stderr.readline()
実行結果
>>> python output.py
標準出力:2015年 12月 7日 月曜日 18時47分09秒 JST
標準エラー出力: wc: 2015: open: No such file or directory
gitの最新commitハッシュを取得
git.py
# git の最新commitハッシュをprint
print cmdline('git log --oneline').stdout.readline()
# 別リポジトリの最新commitハッシュをprint
print cmdline('cd ~/pypi/cf_recommender/ && git log --oneline').stdout.readline()
実行結果
>>> python git.py
6a2ae0a xlsx update by automatic
a2febc4 update readme
標準エラー出力が存在するときchatでエラー通知
chat.py
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals
from subprocess import PIPE, Popen
def cmdline(command):
"""
コマンドを実行する
:param command: str
:return: Popen
"""
return Popen(
args=command,
stdout=PIPE,
stderr=PIPE,
shell=True
)
def chat(message):
# ダミー実装
print 'ERROR:' + message
# 標準エラー出力時にエラー内容をchatで通知
cmd = [
'python manage.py test_json',
'python manage.py test_battle',
]
# コマンド実行時の接頭語, && で複数コマンドをチェインする
prefix = 'cd ~/application/ && {}'
for _cmd in cmd:
command = prefix.format(_cmd)
p = cmdline(command)
print 'command:' + command
# 標準エラー出力が存在するときはchatで通知
errors = p.stderr.readlines()
if errors:
error_message = ''.join(errors)
chat(error_message)
実行結果
command:cd ~/application/ && python manage.py test_json
ERROR:Traceback (most recent call last):
File "manage.py", line 10, in <module>
...
IOError: [Errno 2] No such file or directory: u'..../test.json'
command:cd ~/application/ && python manage.py test_battle
もっと便利な方法を知っている人がきっといるはず( ・ㅂ・)و