最終投稿日:2022年6月18日
Python基本(例外処理・ログ)
例外処理基本構文
基本的な構文は「try ~ catch ~ finally」ですが、
Python は【catch】の代わりに【except】となります。
Python は【catch】の代わりに【except】となります。
例)
def must_zero( i ):
if i != 0:
raise ValueError( 'hoge' ) ※raise は、俗にいう thow に対応します try:
must_zero(1)
except ValueError as e: ※例外をキャッチ
print( e )
print( e.args )
else: ※例外が発生しなかった場合に処理されるブロック
print( '例外なし!' )
finally: ※絶対に処理されるブロック
print( '後処理。。' )
if i != 0:
raise ValueError( 'hoge' ) ※raise は、俗にいう thow に対応します try:
must_zero(1)
except ValueError as e: ※例外をキャッチ
print( e )
print( e.args )
else: ※例外が発生しなかった場合に処理されるブロック
print( '例外なし!' )
finally: ※絶対に処理されるブロック
print( '後処理。。' )
例外を定義する
class MyErr(Exception): ※自作エラークラス
__msg = ''
def __init__(self, msg):
self.__msg = msg
def getErrMsg(self):
return self.__msg
def __init__(self, msg):
self.__msg = msg
def getErrMsg(self):
return self.__msg
例)
def fun1(): ※関数1
fun2(0) def fun2(i): ※関数2
try:
# a = 10 / i
raise MyErr('まいえらー') ※自作エラークラスをスローする
except ZeroDivisionError as e:
# import traceback
# import os
# fpas = os.path.dirname(os.path.abspath(__file__))
# pas_name = os.path.join(fpas, 'hoge_error.log')
# with open(pas_name, 'a') as f:
# traceback.print_exc(file = f) ※トレースバックはファイルに出力する事も可能
print(e) if __name__ == '__main__':
try:
fun1()
except MyErr as e: ※「except MyErr」を設定している場所でキャッチされる
print(e.getErrMsg())
fun2(0) def fun2(i): ※関数2
try:
# a = 10 / i
raise MyErr('まいえらー') ※自作エラークラスをスローする
except ZeroDivisionError as e:
# import traceback
# import os
# fpas = os.path.dirname(os.path.abspath(__file__))
# pas_name = os.path.join(fpas, 'hoge_error.log')
# with open(pas_name, 'a') as f:
# traceback.print_exc(file = f) ※トレースバックはファイルに出力する事も可能
print(e) if __name__ == '__main__':
try:
fun1()
except MyErr as e: ※「except MyErr」を設定している場所でキャッチされる
print(e.getErrMsg())
ログの基本
ログを扱うには[logging]モジュールをインポートします
例)
import logging
logger = logging.getLogger('hoge') ※hoge という名前でログインスタンスを初期化
logger.setLevel(logging.ERROR) ※ログレベルを error 以上とする(40をセットしてもOK)
logger.error('エラーだよ!!!') ※エラーレベル[error]で出力する
logger.warning('わ~にんぐだよ!!!') ※エラーレベル[warning]で出力する
【実行結果】
画面に「エラーだよ!!!」と出力される(レベル[warning]は出力されない)
logger = logging.getLogger('hoge') ※hoge という名前でログインスタンスを初期化
logger.setLevel(logging.ERROR) ※ログレベルを error 以上とする(40をセットしてもOK)
logger.error('エラーだよ!!!') ※エラーレベル[error]で出力する
logger.warning('わ~にんぐだよ!!!') ※エラーレベル[warning]で出力する
【実行結果】
画面に「エラーだよ!!!」と出力される(レベル[warning]は出力されない)
【メモ】
ログのレベルは以下の種類があります
ログレベル Value 対応するメソッド
----------------+----------+----------------------
[logging]モジュールの basicConfig メソッドを使うと例えば全体のログレベルの設定もできます。
----------------+----------+----------------------
CRETICAL 50 critical fatal
ERROR 40 error exception
WARNING 30 warning
INFO 20 info
DEBUG 10 debug
NOTSET 0
ERROR 40 error exception
WARNING 30 warning
INFO 20 info
DEBUG 10 debug
NOTSET 0
例)
logging.basicConfig(level=logging.ERROR)
● 名前の意味
logging のインスタンスを任意の名前で初期化するのには意味があり、
例えば他人のモジュールを利用する場合は、初期化した名前が分かると利用者が自由にログレベルを調整する事が可能です。
例えば他人のモジュールを利用する場合は、初期化した名前が分かると利用者が自由にログレベルを調整する事が可能です。
例)
---------------------------------------------------------------------------------------------------
import logging
def tanin( i ): ※他人のモジュールのつもり
logger = logging.getLogger('hoge') ※hoge でログを初期化している
logger.warning( 'ワーニングだよ。。%s', i )
--------------------------------------------------------------------------------------------------- tanin(1) ※メソッドを実行するとログが出力される(デフォルトのログレベルは warning のため)
myLogger = logging.getLogger('hoge')
※同じ名前でログインスタンスを初期化する(インスタンス名は適当で良い)
myLogger.setLevel(40) ※ログレベルを ERROR に上げる
tanin(2) ※このメソッドではログは出力されない
myLogger.setLevel(30) ※ログレベルを WARNING に下げる
tanin(3) ※ふたたびログが出力される
import logging
def tanin( i ): ※他人のモジュールのつもり
logger = logging.getLogger('hoge') ※hoge でログを初期化している
logger.warning( 'ワーニングだよ。。%s', i )
--------------------------------------------------------------------------------------------------- tanin(1) ※メソッドを実行するとログが出力される(デフォルトのログレベルは warning のため)
myLogger = logging.getLogger('hoge')
※同じ名前でログインスタンスを初期化する(インスタンス名は適当で良い)
myLogger.setLevel(40) ※ログレベルを ERROR に上げる
tanin(2) ※このメソッドではログは出力されない
myLogger.setLevel(30) ※ログレベルを WARNING に下げる
tanin(3) ※ふたたびログが出力される
【メモ】
当然だが他人のモジュール側で setLevel していないのが条件となる。
自分のソース側でも基本的には setLevel をせず、設定ファイル等で setLevel をすれば自由にレベルの操作が可能です。
ハンドラーとフォーマット
ログレベルの他に、ハンドラーでログの出力先を決め、フォーマットでログの内容を決めます。
例)
import logging
from datetime import datetime myPath = '/home/guest/python15h/chapter01/' ※出力先のパス
myLogFile = datetime.now().strftime('%Y%m%d') + '_myLog.log'
※日付単位のファイル名とする
logger = logging.getLogger('hoge') ※logging のインスタンス作成
handler = logging.FileHandler( filename = myPath + myLogFile, encoding='utf-8' )
※ログ出力先を設定した handler オブジェクト作成
fmt = logging.Formatter('%(asctime)s %(levelname)s [%(name)s][%(threadName)s] %(message)s')
※ログのフォーマット設定した fmt オブジェクト作成
handler.setFormatter(fmt)
※handler オブジェクトにフォーマットをセットする
logger.addHandler(handler)
※logging のインスタンスに handler を追加する
logger.warning('ワーニングだよ!!') ※この状態でログ出力処理をす!
from datetime import datetime myPath = '/home/guest/python15h/chapter01/' ※出力先のパス
myLogFile = datetime.now().strftime('%Y%m%d') + '_myLog.log'
※日付単位のファイル名とする
logger = logging.getLogger('hoge') ※logging のインスタンス作成
handler = logging.FileHandler( filename = myPath + myLogFile, encoding='utf-8' )
※ログ出力先を設定した handler オブジェクト作成
fmt = logging.Formatter('%(asctime)s %(levelname)s [%(name)s][%(threadName)s] %(message)s')
※ログのフォーマット設定した fmt オブジェクト作成
handler.setFormatter(fmt)
※handler オブジェクトにフォーマットをセットする
logger.addHandler(handler)
※logging のインスタンスに handler を追加する
logger.warning('ワーニングだよ!!') ※この状態でログ出力処理をす!
【オブジェクトの階層イメージ】
+-----------------------------------+
| [ logging ]OBJ |
| ログのレベル設定、出力処理 |
| +-------------------------------+ |
| | [ handler ]OBJ | |
| | ログの出力先を設定 | |
| | +---------------------------+ | |
| | | [ fmt ]OBJ | | |
| | | ログの出力内容を設定 | | |
| | +---------------------------+ | |
| +-------------------------------+ |
+-----------------------------------+
| [ logging ]OBJ |
| ログのレベル設定、出力処理 |
| +-------------------------------+ |
| | [ handler ]OBJ | |
| | ログの出力先を設定 | |
| | +---------------------------+ | |
| | | [ fmt ]OBJ | | |
| | | ログの出力内容を設定 | | |
| | +---------------------------+ | |
| +-------------------------------+ |
+-----------------------------------+
● ログフォーマットの種類
%(asctime)s ※ログが生成された日時を出力する。datefmt引数で日時のフォーマットの制御できる。
%(levelname)s ※ログレベルを出力する
%(pathname)s ※ログが出力されたソースコードファイルのフルパスを出力する
%(module)s ※ログが出力されたモジュール名を出力する
%(funcName)s ※ログが出力された関数名を出力する
%(message)s ※ログのメッセージ本体を出力する
%(levelname)s ※ログレベルを出力する
%(pathname)s ※ログが出力されたソースコードファイルのフルパスを出力する
%(module)s ※ログが出力されたモジュール名を出力する
%(funcName)s ※ログが出力された関数名を出力する
%(message)s ※ログのメッセージ本体を出力する
ロガーをファイルから読み込む
logging.config モジュールを使ってファイルから設定を読み込む事ができます。
[○○○.conf]ファイルに設定を記述します。
設定のルールは以下となる
-------------------------------------------------------------------------------------------------------------------
[○○○.conf]ファイルに設定を記述します。
設定のルールは以下となる
[loggers] ※名前は固定
keys=○○○,△△△,□□□
※logging インスタンスを作成する際の名前を設定する(複数設定する場合はカンマで区切る) [handlers] ※名前は固定
keys=○○○Handler,△△△Handler ※ハンドラーの名前を設定する(名前は任意でよい) [formatters] ※名前は固定
keys=○○○Formatter,△△△Formatter ※フォーマットの名前を設定する(名前は任意でよい) [logger_○○○] ※個別の設定となる。[loggers]で設定した各名前を指定する
level=INFO ※レベルを設定する。DEBUG,INFO,WARNING,ERROR 等
handlers=○○○Handler ※[handlers]で設定した各名前を指定する
qualname=○○○ ※[logger_○○○]の[○○○]と同じ名前とする [handler_○○○Handler] ※個別の設定となる。[handlers]で設定した各名前を指定する
class=FileHandler ※ハンドラーの属性を設定(ファイル出力)
formatter=○○○Formatter ※[formatters]で設定した各名前を指定する
args=('logger.log',) ※出力パスを指定(第2引数は空で良い) [formatter_○○○Formatter] ※個別の設定となる。[formatters]で設定した各名前を指定する
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s ※出力内容を設定する
datefmt=%Y-%m-%d %H-%M-%S ※日時のフォーマットを指定する ※上記の設定を必要分だけ記述する!
例)keys=○○○,△△△,□□□
※logging インスタンスを作成する際の名前を設定する(複数設定する場合はカンマで区切る) [handlers] ※名前は固定
keys=○○○Handler,△△△Handler ※ハンドラーの名前を設定する(名前は任意でよい) [formatters] ※名前は固定
keys=○○○Formatter,△△△Formatter ※フォーマットの名前を設定する(名前は任意でよい) [logger_○○○] ※個別の設定となる。[loggers]で設定した各名前を指定する
level=INFO ※レベルを設定する。DEBUG,INFO,WARNING,ERROR 等
handlers=○○○Handler ※[handlers]で設定した各名前を指定する
qualname=○○○ ※[logger_○○○]の[○○○]と同じ名前とする [handler_○○○Handler] ※個別の設定となる。[handlers]で設定した各名前を指定する
class=FileHandler ※ハンドラーの属性を設定(ファイル出力)
formatter=○○○Formatter ※[formatters]で設定した各名前を指定する
args=('logger.log',) ※出力パスを指定(第2引数は空で良い) [formatter_○○○Formatter] ※個別の設定となる。[formatters]で設定した各名前を指定する
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s ※出力内容を設定する
datefmt=%Y-%m-%d %H-%M-%S ※日時のフォーマットを指定する ※上記の設定を必要分だけ記述する!
-------------------------------------------------------------------------------------------------------------------
【hoge.conf】
[loggers]
keys=root,myHoge,myFoo ※root は必要 [handlers]
keys=myHogeHandler,myFooHandler [formatters]
keys=myHogeFormatter,myFooFormatter [logger_root]
handlers= ※root は特に設定しない [logger_myHoge]
level=INFO
handlers=myHogeHandler
qualname=myHoge [logger_myFoo]
level=ERROR
handlers=myFooHandler
qualname=myFoo [handler_myHogeHandler]
class=handlers.TimedRotatingFileHandler
※この設定でログローテートができる(毎日新しいファイルにログを出力)
formatter=myHogeFormatter
args=('/home/guest/python15h/chapter01/logger.log','D', 1, 0, 'utf-8')
※ 第2引数に「D」を指定(毎日)
※【'D'】class=handlers.TimedRotatingFileHandler の専用の引数です
※【'a', 'utf-8'】class=FileHandler の時はこっち [handler_myFooHandler]
class=StreamHandler
formatter=myFooFormatter
args=(sys.stdout,) [formatter_myHogeFormatter]
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s
datefmt=%Y%m%d% H%M%S
※class=handlers.TimedRotatingFileHandler の場合のみ使用できます [formatter_myFooFormatter]
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s
datefmt=%Y-%m-%d %H-%M-%S
※class=handlers.TimedRotatingFileHandler の場合のみ使用できます
-------------------------------------------------------------------------------------------------------------------
keys=root,myHoge,myFoo ※root は必要 [handlers]
keys=myHogeHandler,myFooHandler [formatters]
keys=myHogeFormatter,myFooFormatter [logger_root]
handlers= ※root は特に設定しない [logger_myHoge]
level=INFO
handlers=myHogeHandler
qualname=myHoge [logger_myFoo]
level=ERROR
handlers=myFooHandler
qualname=myFoo [handler_myHogeHandler]
class=handlers.TimedRotatingFileHandler
※この設定でログローテートができる(毎日新しいファイルにログを出力)
formatter=myHogeFormatter
args=('/home/guest/python15h/chapter01/logger.log','D', 1, 0, 'utf-8')
※ 第2引数に「D」を指定(毎日)
※【'D'】class=handlers.TimedRotatingFileHandler の専用の引数です
※【'a', 'utf-8'】class=FileHandler の時はこっち [handler_myFooHandler]
class=StreamHandler
formatter=myFooFormatter
args=(sys.stdout,) [formatter_myHogeFormatter]
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s
datefmt=%Y%m%d% H%M%S
※class=handlers.TimedRotatingFileHandler の場合のみ使用できます [formatter_myFooFormatter]
format=%(asctime)s - %(levelname)s- %(name)s - %(message)s
datefmt=%Y-%m-%d %H-%M-%S
※class=handlers.TimedRotatingFileHandler の場合のみ使用できます
【common.py】
import logging
import logging.config
import os class MyLogger:
def gerLogger(self, name):
logging.config.fileConfig(os.path.dirname(__file__) + '/hoge.conf')
※どこから呼ばれても良い様に絶対パスにする
return logging.getLogger(name)
-------------------------------------------------------------------------------------------------------------------
import logging.config
import os class MyLogger:
def gerLogger(self, name):
logging.config.fileConfig(os.path.dirname(__file__) + '/hoge.conf')
※どこから呼ばれても良い様に絶対パスにする
return logging.getLogger(name)
【○○○.py】
from common import MyLogger
myHoge = MyLogger().gerLogger('myHoge')
myHoge.info('エラーなのだー!') ※設定ファイルの通り[logger.log]に出力する myFoo = MyLogger().gerLogger('myFoo')
myFoo.error('エラーっす!') ※設定ファイルの通りコンソールに出力する
-------------------------------------------------------------------------------------------------------------------
myHoge.info('エラーなのだー!') ※設定ファイルの通り[logger.log]に出力する myFoo = MyLogger().gerLogger('myFoo')
myFoo.error('エラーっす!') ※設定ファイルの通りコンソールに出力する




