最終投稿日:2022年6月18日
Django(バッチ)
カスタムコマンド
Djangoにはデフォルトでコマンドラインツールが付属しており、例えば次のような処理をコマンドラインから実行することができます。
python manage.py startapp sample => アプリケーションの作成
python manage.py migrate => DBマイグレーションの実行
python manage.py shell => インタラクティブShellの起動
python manage.py runserver => 開発サーバーの起動 この他にも様々なコマンドが用意されており python manage.py とタイプすると、使用できるコマンドの一覧を表示できます。
より詳細に特定のコマンドのヘルプを参照するには python manage.py help runserver のように help に続けて参照したいコマンドの名称を入力します。 Djangoのコマンドラインツールには、コマンドを追加するための仕組みが用意されています。
カスタムコマンドを追加すると、次のようにコマンドラインツールから実行することができます。
python manage.py [カスタムコマンド名]
例)
bat ファイルからの引数を受け取る
例)
python manage.py startapp sample => アプリケーションの作成
python manage.py migrate => DBマイグレーションの実行
python manage.py shell => インタラクティブShellの起動
python manage.py runserver => 開発サーバーの起動 この他にも様々なコマンドが用意されており python manage.py とタイプすると、使用できるコマンドの一覧を表示できます。
より詳細に特定のコマンドのヘルプを参照するには python manage.py help runserver のように help に続けて参照したいコマンドの名称を入力します。 Djangoのコマンドラインツールには、コマンドを追加するための仕組みが用意されています。
カスタムコマンドを追加すると、次のようにコマンドラインツールから実行することができます。
python manage.py [カスタムコマンド名]
● ディレクトリの作成
カスタムコマンドのディレクトリは任意のアプリ内に作成します。
※ディレクトリ名は固定です
[hoge]
|
+---【management】
|
+--- [__init__.py]
|
+---【commands】
|
+--- [__init__.py]
※ディレクトリ名は固定です
[hoge]
|
+---【management】
|
+--- [__init__.py]
|
+---【commands】
|
+--- [__init__.py]
● コマンドの作成
ファイル名は任意です。
【サンプル04】で作成した books テーブルのレコード数をカウントする count_entry.py を作成します。
※アプリ名:booktitle モデルクラス名:Books
カスタムコマンドは BaseCommand クラスを継承してクラスを作成します。
実際の処理本体は handle メソッド内に記載します。
例)
from django.core.management.base import BaseCommand
#3つ上の models.py の Books クラスをインポートしている
from ...models import Books
#BaseCommand を継承する
class Command(BaseCommand):
#help コマンドで表示される内容を定義
help = 'テーブル books のレコード数をカウントする'
#受け取るパラメータの定義
def add_arguments(self, parser):
#第1引数を book_id という名前で受け取る。値は数値とする。
parser.add_argument('book_id', type=int, help='主キー')
#第2引数を price という名前で受け取る。値は数値とする。
parser.add_argument('price', type=int, help='価格')
#このメソッドがメインの処理をする
def handle(self, *args, **options):
#add_arguments メソッドで定義した名前で値を受け取る
id = options['book_id']
pc = options['price']
book_count = Books.objects.filter(id__gt=id, price=pc).count()
#コマンドプロンプトに表示するお約束の書き方なのかな。
self.stdout.write(self.style.SUCCESS('Book count = "%s"' % book_count))
【サンプル04】で作成した books テーブルのレコード数をカウントする count_entry.py を作成します。
※アプリ名:booktitle モデルクラス名:Books
カスタムコマンドは BaseCommand クラスを継承してクラスを作成します。
実際の処理本体は handle メソッド内に記載します。
例)
from django.core.management.base import BaseCommand
#3つ上の models.py の Books クラスをインポートしている
from ...models import Books
#BaseCommand を継承する
class Command(BaseCommand):
#help コマンドで表示される内容を定義
help = 'テーブル books のレコード数をカウントする'
#受け取るパラメータの定義
def add_arguments(self, parser):
#第1引数を book_id という名前で受け取る。値は数値とする。
parser.add_argument('book_id', type=int, help='主キー')
#第2引数を price という名前で受け取る。値は数値とする。
parser.add_argument('price', type=int, help='価格')
#このメソッドがメインの処理をする
def handle(self, *args, **options):
#add_arguments メソッドで定義した名前で値を受け取る
id = options['book_id']
pc = options['price']
book_count = Books.objects.filter(id__gt=id, price=pc).count()
#コマンドプロンプトに表示するお約束の書き方なのかな。
self.stdout.write(self.style.SUCCESS('Book count = "%s"' % book_count))
【メモ】
メソッド add_arguments で受け取る引数を定義できるが、不特定多数のパラメータを受け取りたい場合は以下の様にするとリスト型で受け取れる例)
def add_arguments(self, parser):
#book_id という名前で複数受け取れる
parser.add_argument('book_id', nargs='+', type=int)
def handle(self, *args, **options):
#for で回せる
for book_id in options['book_id']: ※因みに起動させるコマンドは以下の様にスペース区切りの引数となる
python manage.py count_entry 1 2 3 4 5 6
#book_id という名前で複数受け取れる
parser.add_argument('book_id', nargs='+', type=int)
def handle(self, *args, **options):
#for で回せる
for book_id in options['book_id']: ※因みに起動させるコマンドは以下の様にスペース区切りの引数となる
python manage.py count_entry 1 2 3 4 5 6
● カスタムコマンドの確認
python manage.py を実行すると追加したカスタムコマンドが追加されているのを確認できます。
以下の様な感じ。
[booktitle]
count_entry
以下の様な感じ。
[booktitle]
count_entry
● カスタムコマンドの実行
以下を実行する。
例)
python manage.py count_entry 1 1200 ※count_entry.py で作成したコマンド
結果)
Book count = "1"
例)
python manage.py count_entry 1 1200 ※count_entry.py で作成したコマンド
結果)
Book count = "1"
● bat ファイルを作成する
サンプルを実行する bat ファイルは以下の様に書けます
例)
例)
[config.bat]
set myPath=C:\Users\xxxx\Desktop\Python\Django\sample01
set myLog=C:\Users\xxxx\Desktop\Python\Django\
[hoge.bat]
@echo off
rem ---------------------------
rem パイソン
call config.bat
cd %myPath%
python manage.py count_entry 1 1200 > %myLog%log.txt 2>&1 ※ログを出力する
set myPath=C:\Users\xxxx\Desktop\Python\Django\sample01
set myLog=C:\Users\xxxx\Desktop\Python\Django\
[hoge.bat]
@echo off
rem ---------------------------
rem パイソン
call config.bat
cd %myPath%
python manage.py count_entry 1 1200 > %myLog%log.txt 2>&1 ※ログを出力する
【メモ】
| @ | @cd c:\... と @ を付けるとプロンプトにそのコマンドが表示されなくなります |
| echo off |
以降のコマンドは非表示となる @echo off とすると自身の行も表示となる |
| echo on | 以降のコマンドは表示となる |
| echo ほげ |
メッセージを表示する echo. とすると空白行となる |
| rem コメント |
コメント行 @rem とすれば表示されない |
| set 変数名=値 |
変数をセットする イコールの前後にスペースを入れない事! 変数を参照する場合は、変数名を「%」で囲みます |
| call | 他の bat ファイルを読み込む(共通ファイル等) call hoge.bat の様に記述する |
| hoge > log.txt 2>&1 |
外部ファイルに出力する log.txt は実際はフルパスにした方が良い |
例)
hoge.bat 1 2 3
引数1:%1
引数2:%2
引数3:%3
引数1:%1
引数2:%2
引数3:%3
スレッド(Thread)
基本的には threading モジュールの Thread クラスに処理したいメソッドを引数に渡して好きなタイミングで実行する感じ。
例)
例)
import threading
import time
#スレッド処理させたいメソッド
def hoge(num):
for i in range(10):
#threading.currentThread().getName() で、定義したスレッド名を取得できる
print(threading.currentThread().getName() + str(i * num))
#1秒処理を停止させる
time.sleep(1) """ メイン処理 """
#スレッド名を定義(省略可)、スレッドメソッド指定、パラメータも指定できる
t = threading.Thread(name='hogehoge',target=hoge,args=(2,))
#start() メソッドで実行できる
t.start()
import time
#スレッド処理させたいメソッド
def hoge(num):
for i in range(10):
#threading.currentThread().getName() で、定義したスレッド名を取得できる
print(threading.currentThread().getName() + str(i * num))
#1秒処理を停止させる
time.sleep(1) """ メイン処理 """
#スレッド名を定義(省略可)、スレッドメソッド指定、パラメータも指定できる
t = threading.Thread(name='hogehoge',target=hoge,args=(2,))
#start() メソッドで実行できる
t.start()
python から外部スクリプト実行
import subprocess
ret = subprocess.run('C:/Users/xxxx/Desktop/Python/Django/hoge.bat 1 1200')
#終了コード 0:正常
print(ret.returncode)
又は
import subprocess
ret = subprocess.Popen('C:/Users/xxxx/Desktop/Python/Django/hoge.bat 1 1200')
#このコード無くすと非同期となる
code = ret.wait()
#終了コード 0:正常
print(code)
ret = subprocess.run('C:/Users/xxxx/Desktop/Python/Django/hoge.bat 1 1200')
#終了コード 0:正常
print(ret.returncode)
又は
import subprocess
ret = subprocess.Popen('C:/Users/xxxx/Desktop/Python/Django/hoge.bat 1 1200')
#このコード無くすと非同期となる
code = ret.wait()
#終了コード 0:正常
print(code)
【メモ】
subprocess.run での実行はメインプログラムは外部スクリプトの実行終了を待ちます。
そのため、戻り値の returncode メソッドで実行結果が正常か異常かを知ることができます。
また、subprocess.Popen は非同期処理となり、外部スクリプトの終了を待ちません。
しかし、戻り値の wait メソッドを実行すると同期処理となり、終了コードを取得できます。
そのため、戻り値の returncode メソッドで実行結果が正常か異常かを知ることができます。
また、subprocess.Popen は非同期処理となり、外部スクリプトの終了を待ちません。
しかし、戻り値の wait メソッドを実行すると同期処理となり、終了コードを取得できます。




