外部モジュールのインポートエラー
Terminalに モジュール名がnot found となっていてエラーが出ていました。今まで使えていたものが突然使えなくなりVSCodeの画面でもモジュール名の下に波線がでました。
VSCodeの右下を見るとインタープリターが違うものになっており、クリックして自分の使っている仮想環境のものに戻そうとしましたが候補に出てきません。
仮想環境はvenvを使っています。仮想環境を作るとVScodeでは自動に読み込まれるようですが、何かでうまく行かなくなってしまったようです。
Windowsの場合 Ctrl + Shift + Pで VScodeのsetting.jsonを開きます。
"python.pythonPath": "/home/username/projectname/venv/bin/python",
"python.analysis.extraPaths": [
"/home/username/projectname/venv/lib/python3.10/site-packages"
]
※/venv/より上の階層は自分の環境のパスを設定してください。
これを記載して保存しVSCodeを再起動すると直り、インタープリターにもvenvが表示されるようになりました。
“python.pythonPath” はPython インタプリタのパスを指定する設定です。VSCode がどの Python インタプリタ(仮想環境やシステム環境)を使うべきかを定義。仮想環境を有効にし、実行する Python コードやターミナルで使用する Python のバージョンを決定。
“python.analysis.extraPaths” はPython コードの静的解析や補完候補を提供する際に、追加で参照するパスを指定する設定。補完機能がPYTHONPATHに含まれないディレクトリ内のコードやライブラリを参照できるようにします。特定のモジュールが仮想環境のsite-packagesディレクトリに存在する場合や、プロジェクト内のカスタムモジュールにアクセスする場合に設定します。
Django setting.pyでのログ出力設定
Djangoの実行結果をTerminalで見る時、デフォルトだと詳しくエラーがでないので setting.pyでエラーの出力レベルを調整します。下記を記載し、必要に応じ各項目を調整。
LOGGING = {
'version': 1,
'disable_existing_loggers': False, # 他のロガーを無効にしない
'handlers': {
'console': {
'level': 'DEBUG', # コンソールに出力するレベル
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django': {
'level': 'ERROR', # djangoのログはERROR以上
'handlers': ['console'],
'propagate': False,
},
'django.request': {
'level': 'ERROR', # リクエスト関連のログもERROR以上
'handlers': ['console'],
'propagate': False,
},
'django.db.backends': {
'level': 'ERROR', # DB関連のログもERROR以上
'handlers': ['console'],
'propagate': False,
},
'django.security': {
'level': 'ERROR', # セキュリティ関連のログもERROR以上
'handlers': ['console'],
'propagate': False,
},
# カスタムロガーの設定
'stock_content.views.theme.theme_delete_with_user_order': {
'level': 'DEBUG', # 自作ビューのログはDEBUGで出力
'handlers': ['console'],
'propagate': False,
},
},
}
仮想環境 venvでのCronの注意点
Djangoのコマンドファイルを作ってCronで動かした時のエラー対処です。親コマンドファイルから子コマンドファイルを読み込んで使うときにモジュールを読み込んでいないエラーが出ました。
Terminalで仮想環境に入って実行するとうまくいくのですが、Cronで実行するとエラーになります。
log_file = '/to path/cron_yf_to_db.log' # ログファイルのパス
manage_py_path = '/to path/manage.py' # manage.pyへのフルパス
with open(log_file, 'a') as log:
result = subprocess.run(
['python3', manage_py_path, 'command file path', str(code)],
check=True,
stdout=log, # ファイルオブジェクトに書き込み
stderr=log # 同じファイルにエラー出力も書き込み
上記にする前は下記のような記載でした。stodoutのところがsubprocess.PIPEからlogに変わります。
result = subprocess.run(
['python3', 'manage.py', 'command file path', str(code)],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
command file path は manage.py ○○○○ と実行するときに入れる○○○○です。置き換えてください。
これでログを見ると、/home/username/.local/lib/python3.8/site-packages/django/conf/__init__.py
という表記が出てきました。python3.10で動かしているはずが、3.8になっていました。仮想環境ではなくサーバーのPythonが動いてしまっているようです。
親から子へcodeという変数を投げているので、子コマンドファイルに下記を記載しておくとログでちゃんとデータが親から子に渡っているかも確認できます。
self.stdout.write(self.style.SUCCESS(f'■子コマンドファイル■Received code: {code}'))
少し長くなりますが、下記のように仮想環境を明確に表記するとうまくいきます。
*/2 * * * * PATH=/venvまでのパス/venv/bin:$PATH /venvまでのパス/venv/bin/python /Django manage.pyまでのパス/manage.py コマンド名