質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Q&A

解決済

4回答

3787閲覧

cronでの定期実行で標準入出力が処理完了まで出力されない

yamato_user

総合スコア2321

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

cron

cronは、Unix系OS上でデーモンプロセスとして動作する、スクリプトの自動実行が可能なジョブスケジューラです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

0グッド

0クリップ

投稿2018/12/25 03:25

下記の構成でPythonスクリプトを定期実行しています。
標準出力はcron_normal.logに、標準エラー出力はcron_error.logにしています。

test.py

import time print("test") time.sleep(100) print "test"

test.sh

python3.6 test.py

crontab -e

00 12 * * * test.sh 1>cron_normal.log 2>cron_error.log

状況
まず、Pythonスクリプトの処理が終了するまで、一切の出力がありません。また、途中でエラーが出ると、それまでに出力されるはずだった標準出力は無視され、標準エラー出力のみ書き込まれます

質問
Pythonスクリプトからの出力を、処理の終了を待たずに、順次ファイルに書き込むにはどうすればよいでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

cronジョブでは試していないのですが、flushを併用してみたらいかがでしょうか。標準入出力のflushはpython3ではバージョンによって使い方に差異があるようですので、

Python3

1# 3.3以降なら 2print("test", flush=True) 3 4# 3.3より前なら 5import sys 6print("test"); 7sys.stdout.flush()

なかんじで。


コメントでの補足を受けて、追記しました

標準入出力のフラッシュとかcronジョブ特有の問題とかではなく、コードにエラーがある為にスクリプトの実行がされていないようです。Ubuntu17.04 + python3.5.3 で試した例を示します。

スクリプトをtest01.pyとして以下を用意します。(ダメ押しでflushしています)

Python3

1# test01.py 2import time 3import sys 4 5print("test1", flush=True) 6print("test2", flush=True) 7sys.stdout.flush(); 8 9time.sleep(5) 10v = 1 11# cause exception 12print("str " + v) 13# syntax error 14print "test3"

これを実行すると、Syntax Errorが報告されるだけで、そもそも"test1"も"test2"も出力されません。コードが実行されていないのでしょう。(まぁ、当たり前と言えば当たり前)

Bash

1$ python3 test01.py 2 File "test01.py", line 13 3 print "test3" 4 ^ 5SyntaxError: Missing parentheses in call to 'print'

修正して、python3としては文法エラーである`print "test03"の部分だけコメントにし、実行します。

bash

1$ python test01.py 2test1 3test2 4Traceback (most recent call last): 5 File "test01.py", line 11, in <module> 6 print("str " + v) 7TypeError: Can't convert 'int' object to str implicitly

ランタイムエラーでExceptionは吐かれますが、"test1", "test2"は出力され、コードが実行されていることが分かります。要は、まず「python3のコードとして完成していなければならない。」が最低条件だと思います。そうすれば、can110さんに実際に試していただいたように出力されるようになるはずです。

おまけですが、py_compileモジュールで文法チェックだけする方法があります。
文法エラーのある状態でtest01.pyをコンパイルした例

Bash

1$ python3 -m "py_compile" test01.py 2 File "test01.py", line 13 3 print "test3" 4 ^ 5SyntaxError: Missing parentheses in call to 'print'

投稿2018/12/25 03:35

編集2018/12/25 05:39
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamato_user

2018/12/25 03:47

ご提示の方法を実施してみましたが、結果は変わらずでした。。。ほかの方法はご存知ないでしょうか?
dodox86

2018/12/25 04:06

コードを見て気づいたのですが、python3とpython2のコードが混在しています。 print("test") time.sleep(100) print "test" print "test" でSyntax Errorで異常終了しませんか? cronジョブにしないで ./test.sh 実行で意図通り動作しますでしょうか。
yamato_user

2018/12/25 04:22

補足いたします。質問文にもある通り、「エラーが出たら、それまでの標準出力(print("test"))は出力されず、標準エラー出力(print "test")のみが出力されます」。自分の意図としては、どちらの出力も逐次出力させたいです
dodox86

2018/12/25 04:46 編集

そういうことですか。Syntax Errorが発生するコードですと、そもそもpython3による最初のコード解釈でエラーになってコードが実行されていない様子です。なので出力されません。ですのでcronとか標準出力とかの問題ではありません。追記します。
yamato_user

2018/12/25 05:43

print "test"を100/0にしたらいけました。flush=True使って! ありがとうございます
dodox86

2018/12/25 05:49

100/0は0除算例外なだけで文法エラーではないですからね。ともあれ解決(?)してよかったです。
dodox86

2018/12/25 05:52

他の回答者様へも、どうもありがとうございました。ご回答いただいた内容で知らなかったこともありましたので勉強になりました。
guest

0

補足

test.sh 1>~だとtest.shスクリプトが終了するまで書き込まれないようです。
以下のようにpython ~.py 1>~のように直接.pyスクリプトを実行した結果をリダイレクトすると、所望の動作をします。

補足前の回答

当方ラズパイ
Linux rpi2 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l GNU/Linux
Python 3.5.3 (default, Sep 27 2018, 17:25:39) [GCC 6.3.0 20170516] on linux
で以下のソースにて順次ファイルに書き込まれることを確認しました。

なお、他の方も指摘されていますがprint "test"の行でエラー発生しているものと思われます。

Python

1# hoge.py 2import time 3import sys 4for i in range(30): 5 sys.stderr.write('stderr:{}\n'.format(i)) 6 sys.stderr.flush() 7 print('print:{}'.format(i),flush=True) 8 time.sleep(1)
# cron 12 * * * * python3 /home/pi/hoge.py 1> hoge_out.log 2> hoge_err.log

投稿2018/12/25 04:19

編集2018/12/25 05:27
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Pythonに限らず一般的に、プログラムからディスクファイルへの書き出しは一定サイズ溜まってからOSに書き込み要求が出ます。例えば8Kバイトとか。
(一方、端末への書き出しは、普通は改行で行われる)

プログラムで、OSへ書き込み要求が出るように指示するのは、dodox86 さんの回答の通り、flushを行います。水洗トイレを流すときのボタンと同じ。

また、途中でエラーが出ると、それまでに出力されるはずだった標準出力は無視され、標準エラー出力のみ書き込まれます

これはちょっと考えづらいです。プログラムの終了時には、正常終了であれ、異常終了であれ、オープン中のファイルはクローズされるので、その時点で書き込まれるはずです。
(kill -9で殺したとき以外)
何か特別なエラー処理を設定しているのでしょうか?

投稿2018/12/25 04:01

otn

総合スコア84551

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

UNIX 系の標準出力はバッファを使っています。
print 等で標準出力に吐き出しても、バッファがいっぱいになるまでは基本的には標準出力へは出力をしません。
改行コードを出力するとバッファから出力されることが多いですが、これも条件によるので、確実にバッファから出力させたい場合には、既に回答が付いている通り各言語の flush 的な機能を明示的に実行することになります。

投稿2018/12/25 03:47

ssasaki

総合スコア1167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問