Automatic1111のwebui.batを読み解く:Windowsのバッチファイル解析

スポンサーリンク
Stable Diffusion
スポンサーリンク

Stable Diffuisionのwebui、Automatic1111のwebui.batの記述内容を理解して、このバッチファイルの中でどんな処理が行われているか確認してみました。バッチファイルはどのように動いているか理解することで、実際にどんな処理をしているか勉強したいと思います。

automatic1111のファイルは以下のGithubサイトで公開されています。今回は2023/04/02現在の最新バージョン(22bcc7b)を解析対象にしています。

1行目~14行目

ここでは、pythonなどの環境変数の値の取得Pythonが起動できるか確認しています。

@echo off

echo offはバッチファイル実行時にデフォルトではコマンドプロンプトにテキストが出力が、それをオフにします。その前の@については、その行のみを非表示にするコマンドです。@echo offにより、ここの行を含めてすべてのテキストをコマンドプロンプトに出力しないようにします。

if not defined PYTHON (set PYTHON=python)
if not defined VENV_DIR (set "VENV_DIR=%~dp0%venv")

if 条件 (コマンド)で条件に当てはまった場合にカッコ内のコマンドを実行します。definedで環境変数で「PYTHON」および「VENV_DIR」が定義されているか確認して、もし、定義されていない場合はそれぞれ「pythonコマンド」と「%~dp0%venv」を割り当てます。特に「%~dp0」はこのバッチファイルのあるドライブとフルパスを示します。例えば、バッチファイルが”D:\User\example.bat”にある場合は、”D:\User\”を示し、”%~dp0%venv”で文字列”D:\User\venv”を「VENV_DIR」にセットします。

set ERROR_REPORTING=FALSE

エラーメッセージをオフにします。

mkdir tmp 2>NUL

「mkdir tmp」でtmpのフォルダを作成します。2>以降はエラー発生時の処理を示しますが、「NUL」で何もしないようになっています。

%PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
if %ERRORLEVEL% == 0 goto :check_pip
echo Couldn't launch python
goto :show_stdout_stderr

%PYTHON%にはデフォルトのpythonのパスが入っていて、「python -c “”」でコマンドラインでpythonの空コマンドを実行し、うまくいった場合は「>tmp/stdout.txt」で標準出力をstdout.txtに書き込み、エラーが起こった場合は「2>tmp/stderr.txt」で標準エラー出力を書き込みます。「%ERRORLEVEL%」にはコマンドの終了コードが書き込まれます。うまくいった場合は「0」になりますので、「goto :check_pip」で「check_pip」のポイントにジャンプします。一方、エラーが行った場合は、「Couldn’t launch python」と表示して、「goto :show_stdout_stderr」で「show_stdout_stderr」にジャンプします。

正常にPythonが起動できる場合は「check_pip」に進み、起動できない場合はエラーメッセージを表示し、「show_stdout_stderr」でバッチ処理を中断します。

16行目~23行目(:check_pip)

ここでは、pythonのpipインストーラーが正常に起動できるか確認しています。

%PYTHON% -mpip --help >tmp/stdout.txt 2>tmp/stderr.txt
if %ERRORLEVEL% == 0 goto :start_venv

ここでは「python -m pip –help」を実行してpipのヘルプファイルが正常に表示されるか確認しています。エラーが起こった場合は「2>tmp/stderr.txt」で標準エラー出力を書き込みます。正常に起動した場合は「%ERRORLEVEL% == 0」となり、「start_venv」にジャンプします。

if "%PIP_INSTALLER_LOCATION%" == "" goto :show_stdout_stderr

「%PIP_INSTALLER_LOCATION%」が空である場合、「show_stdout_stderr」にジャンプし、処理を中断します。

%PYTHON% "%PIP_INSTALLER_LOCATION%" >tmp/stdout.txt 2>tmp/stderr.txt
if %ERRORLEVEL% == 0 goto :start_venv
echo Couldn't install pip
goto :show_stdout_stderr

%PIP_INSTALLER_LOCATION%」からpipのインストールを試みます。if文で「%ERRORLEVEL%」を確認し、インストールが正常にいった場合は「start_venv」にジャンプし、失敗した場合は、「Couldn’t install pip」を表示し、「show_stdout_stderr」にジャンプし、処理を中断します。

25行目~37行目(:start_venv)

このブロックでは、Pythonの仮想環境を作成します。

if ["%VENV_DIR%"] == ["-"] goto :skip_venv
if ["%SKIP_VENV%"] == ["1"] goto :skip_venv

「%VENV_DIR%」に「-」を設定するか、「%SKIP_VENV%」を「1」にした場合、仮想環境の作成をスキップします。デフォルトでは作成するようになっています。ディスクスペースを節約したいなどの特別の理由がない場合以外は仮想環境を作成した方が良いです。

dir "%VENV_DIR%\Scripts\Python.exe" >tmp/stdout.txt 2>tmp/stderr.txt
if %ERRORLEVEL% == 0 goto :activate_venv

すでに仮想環境が作成されている場合は「activate_venv」にジャンプします。

for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%
%PYTHON_FULLNAME% -m venv "%VENV_DIR%" >tmp/stdout.txt 2>tmp/stderr.txt
if %ERRORLEVEL% == 0 goto :activate_venv
echo Unable to create venv in directory "%VENV_DIR%"
goto :show_stdout_stderr

バッチファイルのfor文は以下のように記述します。

for 変数 in (リスト) do (
    実行するコマンド1
    実行するコマンド2
    ...
)

CALL %PYTHON% -c “import sys; print(sys.executable)”」で、pythonをコマンドラインで起動し、標準ライブラリのsys.executableでpythonのフルパスを出力し、その結果を「%%i」に入ります。ここで、「/f “delims=”」では区切り文字を指定していませんので、結果全体がそのまま「%%i」に入ることになり、その値を「PYTHON_FULLNAME」に設定します。

「echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%」では予定される仮想環境の生成先と元のPythonのフルパスを表示します。

%PYTHON_FULLNAME% -m venv “%VENV_DIR%”」では、指定されたフォルダにvenv仮想環境を作成し、うまくいった場合は、「activate_venv」にジャンプします。

エラーが行った場合は「echo Unable to create venv in directory “%VENV_DIR%”」でエラーメッセージを表示し、「show_stdout_stderr」にジャンプし、処理を中断します。

39行目~41行目(:activate_venv)

set PYTHON="%VENV_DIR%\Scripts\Python.exe"
echo venv %PYTHON%

上記では環境変数「PYTHON」に仮想環境のPythonのPathが設定され、その値を表示しています。

43行目~45行目(:skip_venv)

if [%ACCELERATE%] == ["True"] goto :accelerate
goto :launch

ここでは、環境変数「ACCELERATE」をチェックして、Trueなら、オプションのaccelerateをセットアップします。accelerateはスクリプトの実行速度を最適化し、実行時間を短縮してくれます。使う場合は「accerate」のジャンプして、使わない場合は「launch」にジャンプします。

47行目~50行目(:accelerate)

set ACCELERATE="%VENV_DIR%\Scripts\accelerate.exe"
if EXIST %ACCELERATE% goto :accelerate_launch

accelerate.exe」があれば、「accelerate_launch」にジャンプします。

52行目~55行目(:launch)

%PYTHON% launch.py %*
pause
exit /b

%PYTHON% launch.py %*」ですべての引数を渡して「launch.py」が実行されます。launch.pyでは必要なライブラリのインストールとwebuiのメインプログラムの起動を行い、以降は、Pythonでの処理となります。(バッチファイルの役割はここで終了)

57行目~61行目(:accelerate_launch)

accelerateを使う場合はこちらから起動します。

echo Accelerating
%ACCELERATE% launch --num_cpu_threads_per_process=6 launch.py
pause
exit /b

ここではacceletateから「–num_cpu_threads_per_process=6」というオプションを指定してCPUのスレッド数を6に設定し、並列処理を効率的に行えるようにして、「launch.py」を実行します。

63行目~85行目(エラー処理)

以下はエラー時の処理を記載しています。

echo.
echo exit code: %errorlevel%

「echo.」は空行を出力。「echo exit code: %errorlevel%」で直前のエラーコードを出力します。

for /f %%i in ("tmp\stdout.txt") do set size=%%~zi
if %size% equ 0 goto :show_stderr

「/f」でファイル「tmp\stdout.txt」を「%%i」に代入します。「%%~zi」では「%%i」で指定されたファイル名のファイルサイズを示し、「size」に代入します。「size」が0なら、「show_stderr」にジャンプします。

echo.
echo stdout:
type tmp\stdout.txt

「type tmp\stdout.txt」で「stdout.txt」の内容を表示します。

for /f %%i in ("tmp\stderr.txt") do set size=%%~zi
if %size% equ 0 goto :show_stderr
echo.
echo stderr:
type tmp\stderr.txt

同じく「stderr.txt」のサイズが0ではなければ、内容を出力します。

:endofscript

echo.
echo Launch unsuccessful. Exiting.
pause

起動に失敗したことを表示し、処理を終了します。

webui-user.batの働き

webUIを使うときは、実際には、webui.batを直接起動するのではなく、webui-user.batから間接的に立ち上げます。webui-user.batにはwebui.batやそのあとのlaunch.pyの設定を読み込ませることができます。具体的には、起動したいPythonのバージョンや仮想環境使用の有無についてもwebui-user.batに記述することで処理に反映できますので、起動条件のカスタマイズをするときは、webui-user.batを編集します。(webui.batを変更するとアップデート時にコンフリクトを起こす可能性があります。。。)

@echo off

set PYTHON=
set GIT=
set VENV_DIR=
set COMMANDLINE_ARGS= --no-half-vae --opt-channelslast --autolaunch

call webui.bat

終わりに

今回、WebUI、Automatic1111の起動のバッチファイルを詳しく解析した結果をまとめてみました。Windowsのバッチファイルは普段記述することがなかったので、いろいろ勉強になります。環境によって起動やインストールがうまくいかない場合もこのあたりが分かっているとカスタマイズも可能になりますので、皆さんもご参考ください。(調べながらしましたが、間違いがあったら教えていただけたたらありがたいです。)

コメント