ファイルが更新されていたらスクリプトを実行する 【Python】

programming Python

2つのファイルの新旧を比較して、片方のファイルが更新されていたら(新しくなっていたら)処理を実行する Python のスクリプトついてまとめておきます。

以下の環境で動作確認をしています。
環境: Windows 10 以降、Python 3.X 以降 (+Anaconda)

背景

これまで、Windows パソコン上で Python のスクリプトを使う場合は、コマンドプロンプト(Anaconda Prompt)から Python を実行するか、バッチファイルを作成し、ダブルクリックで実行していました。
しかしながら、同じような作業を繰り返していると、自動化したくなってきます。

とはいえ、Windows のタスクスケジューラの機能を使って、毎日、指定時刻に実行するようにすると、必要のないときも同じ処理が繰り返され、パソコンの劣化が早まるのではないか心配になります。
たとえば、SSD やハードディスク、SD カードは消耗品であり書き込み回数の制約があります。ファイルの出力を伴うような処理を毎日のように自動実行すると、パソコンや消耗品の劣化が早まることになります。無駄な書き込みはできる限り、避けたいところです。

ということで、入力データと出力データのタイムスタンプを比較して、入力データが更新されていたときのみ、指定した任意の Python のスクリプトを実行する方法についてまとめておきます。
具体的には、HTML のカレンダーなどで、予定を記載したテキストファイルを更新したときだけ Python のスクリプトを実行し、HTML のカレンダーを生成する、といった場合です。
加えて、このスクリプトをバッチファイルから呼び出すようにし、Windows のタスクスケジューラに設定しておく手順についてもまとめておきます。

2つのファイルの新旧を比較しているだけですので、比較するファイルのリンクを差し替えれば、好きなようにアレンジできると思います。

設定手順

① デスクトップなどにフォルダを作成してください。
② その中に、以下の3つのファイルを作成してください。
例: “text1.txt”、”text2.txt”、”test1.py”
★ これらは単なるテスト用のファイルですので、(最初は)ファイルには何も書き込まなくてよいです。

③ ①のフォルダの中に、さらに、”file_compare1.py” 等の名前でテキストファイルを作成してください。このテキストファイルに、下記のサンプルスクリプトを貼りつけて保存してください。

実行方法

④ コマンドプロンプト(または、Anaconda Prompt)を起動し、③のスクリプトを実行してください。
具体的には、”python ” と入力し、③のファイルをコマンドプロンプトにドラッグし、[enter] キーを押して実行してください。

⑤ 正常に実行ができたら、②の text1.txt をエディタで開いて上書き保存し(日付・タイムスタンプを更新し)、再度、④の実行をしてみてください。Python のスクリプト(test1.py)を実行する動きになります。
⑥ また、②の text2.txt のほうをエディタで開いて上書き保存し、④の実行をしてみてください。Python のスクリプトはスキップして実行しない動きになります。
※ ⑤、⑥を何度か行い、コマンドプロンプトの表示を比較してみてください。

バッチファイルの設定手順

続いて、④をバッチファイル化する事例についてまとめておきます。
⑦ ①のフォルダの中などでテキストファイルを作成し、バッチファイルの名前(例:bat1.bat)を設定してください。
バッチファイルには、以下を例に、実行するコマンドを記載して保存してください。
記載例
call C:\Users\…\Anaconda3\Scripts\activate.bat
python C:\user\…\file_compare1.py

★ 1行目の Anaconda …としたところは、Anaconda Prompt を使っている場合の記載例です。Anaconda を使っていない場合は、この行は不要です。また、「Users\…\Anaconda3」としたところは、Anaconda の activate.bat があるパスを指定する必要がありますので、各パソコンで確認をしてみてください。パソコンごとに異なっており、通常、ユーザー名となっていると思います。バッチファイルで Anaconda プロンプトから Python を実行する方法は、以下の関連リンクにまとめていますので、関心のある方は参照してください。
★ 2行目の「C:\user…」としたところは、③のスクリプト(file_compare1.py)がある絶対パスとなるように設定してください。
⑧ ⑦のバッチファイル(bat1.bat)をダブルクリックしてみてください。Python が実行できると思います。
★ このバッチファイルを下記のタスクスケジューラに登録しておくと、指定時刻に自動実行できます。
★ また、複数の Python スクリプトを順次実行したい場合は、2行目以降に、同様に複数のコマンドを追加してください。Python のスクリプトが複数あっても、自動で実行できるように設定できます。(このため、バッチファイルから、Python のスクリプトを実行するようにしています。Ruby のスクリプトのように、Python 以外のプログラムを実行したい場合でも、同様に実行できます。)

タスクスケジューラの設定手順

つぎに、上記で作成したバッチファイルをタスクスケジューラに設定する手順について、まとめておきます。
⑨ Windows のタスクスケジューラを起動します。
具体的には、Windows 10 の場合、左下の「ここに入力して検索」の欄に、タスク等と入力し、表示された「タスクスケジューラ」のアイコンをクリックして起動します。
⑩ 「タスクの作成」をクリックし、名前を設定します。
例: “calendar1”
⑪ 「トリガー」タブをクリックし、「新規」をクリックします。
⑫ 実行する期間を設定します。
例: 「毎日」を選択します。
⑬ 実行する時刻を設定します。
例: “2022/02/10” とし、時刻の欄が “23:30:00” となるように設定する。
⑭ 「操作」タブをクリックし、「新規」をクリックします。
「参照」をクリックし、⑧のバッチファイル(例:bat1.bat)を選択し、「開く」をクリックします。
⑮ 「OK」をクリックします。

→ これで設定完了です。
指定した時刻に実行されることを確認してください。
動作テストをする場合は、⑬の時刻を現在時刻の数分後に設定するなどし、動作することを確認してみてください。

うまく動いたら

・ 上記の手順では、Python のスクリプト(test1.py)は空のスクリプトになっていますので、任意の Python のスクリプトに差し替えてみて、Python が実行できるか確認してみてください。このサイト内でサンプルスクリプトを公開していますので、簡単なものをコピー&ペーストで動かしてみてもよいかと思います。
・ また、⑤、⑥で比較するファイルも、実際に使っているファイル/リンクに差し替えてみてください。うまく動くか確認してください。

★ また、下記のサンプルスクリプトでは、一例として、このサイトで別途説明している HTML のカレンダーがすぐに動くよう記載しています。
具体的には、①で作成したフォルダ内に、さらに、下記の「HTML カレンダーを出力する」のスクリプトを追加してみてください。
カレンダーの用途で使う場合は、下記のスクリプトで、file1 = …、file2 = …、cmd1 = …としている3行について、直下でコメントアウトしている行(# を入れた行)と差し替えてください。
そして、テキストファイルでカレンダーの予定をテキストファイルで書き込むと、更新の要否(予定表の更新)を自動判定し、HTML カレンダーを自動生成する動きとなります。予定表が更新されていない場合は、ファイルの出力はしない(無駄なファイルの書き込みはしない)動きとなります。

→ うまく動いたら、さらに応用してみてください。

まとめ

ファイルの新旧を比較し、ファイルが更新されていたら任意の Python のスクリプトを実行する方法についてまとめました。
また、このスクリプトを Windows のタスクスケジューラから実行する手順についてまとめました。

当たり前のような内容ですが、これでハードディスクや SSD、SD カードなどの消耗品の劣化を抑えつつ、カレンダーの自動更新など日々行う定型作業の自動化が可能になります。
なお、日付の新旧比較など、サンプルスクリプトで使っているプログラムは、下記の関連リンクで示した各処理を組み合わせたものです。関心のある方は、関連リンクも参照してみてください。

関連リンク
・ HTML のカレンダーを生成する 【Python】
・ Python で他の Python スクリプトごと実行する方法
・ 一括で日付つきファイル名に変換する 【Python】
・ 数値を文字列に変換するときによく使うコードまとめ 【Python】
・ バッチファイルで Anaconda から Python を実行する方法 【Windows 10】

サンプルスクリプト file_compare1.py

import os 
import time as tm1
import datetime as dt1 
import subprocess as sp1 

def get_timestamp1( file1 ): 
    time1  = os.path.getmtime( file1 )                 # for windows 
    time2 = tm1.localtime( time1 ) 
    format1 = tm1.strftime( "%y%m%d_%H%M%S", time2 ) 
#   time2 = dt1.datetime.fromtimestamp( time1 ) 
#   format1 = "{0:%y%m%d_%H%M%S}".format( time2 ) 
    return format1 

def compare_timestamps1( file1, file2 ): 
    time1 = get_timestamp1( file1 ) 
    time2 = get_timestamp1( file2 ) 
    if time1 > time2: 
        return True 
    else: 
        return False 

path1 = os.path.dirname(__file__) + "/" 

file1 = path1 + "text1.txt" 
file2 = path1 + "text2.txt" 
# file1 = path1 + "schedule1.txt" 
# file2 = path1 + "calendar/calendar1.html" 

ret1 = compare_timestamps1( file1, file2 ) 
print( ret1 ) 

if ret1: 
    print( file1 ) 
    cmd1 = "python " + path1 + "test1.py" 
#   cmd1 = "python " + path1 + "html_calendar1.py" 
    print( cmd1 ) 
    sp1.run( cmd1 ) 
else: 
    print( file2 ) 
タイトルとURLをコピーしました