python3.doc_53
R e i - D r e a m
for Laravel
TOP > Python3 > Django(バッチ)
Guest
login

最終投稿日: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 [カスタムコマンド名]
● ディレクトリの作成
カスタムコマンドのディレクトリは任意のアプリ内に作成します。
※ディレクトリ名は固定です
          [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))
【メモ】
メソッド 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
● カスタムコマンドの確認
python manage.py を実行すると追加したカスタムコマンドが追加されているのを確認できます。
以下の様な感じ。
    [booktitle]
        count_entry
● カスタムコマンドの実行
以下を実行する。
例)
    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    ※ログを出力する
【メモ】
@ @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 は実際はフルパスにした方が良い
bat ファイルからの引数を受け取る
例)
hoge.bat 1 2 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()
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)
【メモ】
subprocess.run での実行はメインプログラムは外部スクリプトの実行終了を待ちます。
そのため、戻り値の returncode メソッドで実行結果が正常か異常かを知ることができます。
また、subprocess.Popen は非同期処理となり、外部スクリプトの終了を待ちません。
しかし、戻り値の wait メソッドを実行すると同期処理となり、終了コードを取得できます。
きっぷる
ログインしてコメントを残そう!!


きっぷる