Python のスニペット集
このページは、Python (3) のスニペットなどをまとめる予定のページです。
目次
注意
- コードのライセンスは CC0 (クレジット表示不要、改変可、商用可) です。
スニペット
演算子
条件演算子
x = 'a'
a = x if x is not None else ''
反復
for i in range(1, 10):
print(i) # 1~9
デコレータ
def trace(f):
import time
def decorator(*args, **kwargs):
print(f'---------- start {f.__name__} (args={args}, kwargs={kwargs}) ----------')
start = time.perf_counter()
f(*args, **kwargs)
t = time.perf_counter() - start
print(f'---------- end {f.__name__} (args={args}, kwargs={kwargs}) time: {t:.10f} ----------')
return decorator
@trace
def func(a, b, c):
print(a, b, c)
func(1, 2, 3)
# 結果
# ---------- start func (args=(1, 2, 3), kwargs={}) ----------
# 1 2 3
# ---------- end func (args=(1, 2, 3), kwargs={}) time: 0.0000020005 ----------
文字列
フォーマット
a = 1
b = 2
s = f'a = {a}, b = {b}'
a = 1
b = 2
s = 'a = %d, b = %02d' % (a, b) # 'a = 1, b = 02'
# from string import Template
s = Template('a = $a, b = $b')
s.substitute({'a': 1, 'b': 2})
パディング
a = 1
s1 = str(1).zfill(4) # 0001
s2 = str(1).rjust(4, '0') # 0001
s3 = format(a, '04') # 0001
s4 = '{0:04}'.format(a) # 0001
s5 = '%04d' % a # 0001
a = 1
s = str(1).ljust(4, '0') # 1000
s3 = format(a, '<04') # 1000
s4 = '{0:<04}'.format(a) # 1000
文字列の検索
s = 'test string'
b = 'str' in s
s = 'test string'
b = s.startswith('test')
s = 'test string'
b = s.endswith('ing')
数値変換
s = '123'
try:
n = int(s)
except:
n = 0
s = '123.45'
try:
n = float(s)
except:
n = 0
list
内包記法
list1 = [{'year': 2022, 'value':100}, {'year': 2023, 'value':200}, {'year': 2024, 'value':300}]
years = [it['year'] for it in list1] # [2022, 2023, 2024]
要素の削除
list1 = [1, 2, 3]
del list1[1]
list1 = [1, 2, 3]
list1.pop(1)
ソート
data = [
{ 'id': 1, 'name': '山田太郎' },
{ 'id': 3, 'name': '斎藤花子' },
{ 'id': 2, 'name': '鈴木次郎' },
]
data2 = sorted(data, key=lambda x: x['id']) # [{'id': 1, 'name': '山田太郎'}, {'id': 2, 'name': '鈴木次郎'}, {'id': 3, 'name': '斎藤花子'}]
data3 = sorted(data, key=lambda x: x['id'], reverse=True) # [{'id': 3, 'name': '斎藤花子'}, {'id': 2, 'name': '鈴木次郎'}, {'id': 1, 'name': '山田太郎'}]
dict
キーの存在確認
d1 = {'a': 1, 'b': 2}
if 'a' in d1:
print(d1['a'])
マージ
d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'd': 4}
d3 = {**d1, **d2} # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
d4 = {**d1, 'e': 5, 'f': 6} # {'a': 1, 'b': 2, 'e': 5, 'f': 6}
d1 = {'a': 1, 'b': 2}
d2 = {'c': 3, 'd': 4}
d3 = d1 | d2
zip
keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values)) # {'a': 1, 'b': 2, 'c': 3}
要素の削除
d = {'a': 1}
d.pop('a', None)
d = { 'a': 1 }
del d['a']
一部のキーのみの dict を取得
d = {'a': 1, 'b': 2, 'c': 3}
keys = ['a', 'b']
d2 = {k:v for k, v in d.items() if k in keys} # {'a': 1, 'b': 2}
日時
現在日時
# from datetime import datetime
dt = datetime.now()
# from datetime import datetime, timezone
dt = datetime.now(timezone.utc)
# from datetime import datetime, timezone, timedelta
jst = timezone(timedelta(hours=+9))
dt = datetime.now(jst)
# from datetime import datetime, timezone
dt = datetime.now()
tz = timezone.utc
dt2 = dt.astimezone(tz)
フォーマット
strftime()
# from datetime import datetime
dt = datetime(2021, 1, 2, 3, 4, 5)
s = dt.strftime("%Y-%m-%d %H:%M:%S") # 2021-01-02T03:04:05
isoformat()
# from datetime import datetime
dt = datetime(2021, 1, 2, 3, 4, 5)
s = dt.isoformat() # 2021-01-02T03:04:05
# from datetime import datetime
dt = datetime(2021, 1, 2, 3, 4, 5)
s = dt.isoformat(' ') # 2021-01-02 03:04:05
分→時間
m = 90
'%d:%02d' % divmod(m, 60) # 1:30 (h:mm)
'%02d:%02d' % divmod(m, 60) # 01:30 (hh:mm)
m = 1470
'%d:%02d' % divmod(m, 60) # 24:30 (h:mm)
'%02d:%02d' % divmod(m, 60) # 24:30 (hh:mm)
時間の切り捨て
# from datetime import datetime
dt = datetime.now()
dt2 = dt.replace(hour=0, minute=0, second=0, microsecond=0)
日の演算 (加算など)
# from datetime import datetime, timedelta
dt = datetime(2021, 1, 31)
dt2 = dt + timedelta(days=1) # 2021-02-01
月の演算 (加算など)
- 外部モジュールの dateutil (relativedelta) を使用しています。(dateutil - powerful extensions to datetime — dateutil 2.8.2 documentation)
# from datetime import datetime
# from dateutil.relativedelta import relativedelta
dt = datetime(2021, 1, 31)
dt2 = dt + relativedelta(months=1) # 2021-02-28
# from datetime import datetime
# from dateutil.relativedelta import relativedelta
dt = datetime(2021, 2, 15)
dt2 = dt + relativedelta(day=1, months=1, days=-1) # 2021-02-28
経過時間
# import time
start = time.time()
# 処理 ...
elapsed = time.time() - start
正規表現
# import re
s = 'abc123'
result = re.fullmatch('[a-zA-Z0-9]+', s)
# import re
s = 'abc123!'
symbol = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
result = re.fullmatch('[a-zA-Z0-9%s]+' % re.escape(symbol), s)
UUID
# import uuid
uuid_str = str(uuid.uuid1())
ファイル
タイムスタンプ変更
# import time
# import os
t = time.mktime((2019, 1, 1, 0, 0, 0, 0, 0, 0)) # 2019-01-01 00:00:00
os.utime('file.txt', (t, t))
sleep
# import time
time.sleep(1)
パス
実行パスからの相対パス解決
# import pathlib
p = str(pathlib.Path(__file__).parent.joinpath('path/to/file.txt')) # /example/test/main.py で動作している場合 /example/test/path/to/file.txt
URL
パス結合
# from urllib.parse import urljoin
p = urljoin('https://exmaple.com/api/', 'path/to/file.txt')
JSON
エンコード
# import json
data = {'a': 1, 'b': 2, 'c': 'テスト'}
s = json.dumps(data)
# import json
data = {'a': 1, 'b': 2, 'c': 'テスト'}
with open('/path/to/data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
デコード
# import json
s = '[1,2,3]'
data = json.loads(s)
# import json
with open('/path/to/data.json', 'r') as f:
data = json.load(f)
INI
読み込み
[section1]
value1=1
# import configparser
config = configparser.ConfigParser()
config.read('settings.ini')
value1 = config['section1']['value1']
書き込み
# import configparser
config = configparser.ConfigParser()
config['a'] = {}
config['a']['b'] = "c"
with open('settings.ini', 'w') as f:
config.write(f)
HTTP
GET
# import urllib.request
url = 'https://example.com/'
headers = {
'Accept-Language': 'ja',
}
data = {
'foo': 1
}
req = urllib.request.Request(f'{url}?{urllib.parse.urlencode(data)}', None, headers)
with urllib.request.urlopen(req) as res:
body = res.read().decode('utf-8')
print(body)
GET (SSL の検証無効化)
# import urllib.request
# import ssl
url = 'https://example.com/'
headers = {
'Accept-Language': 'ja',
}
data = {
'foo': 1
}
req = urllib.request.Request(f'{url}?{urllib.parse.urlencode(data)}', None, headers)
context = ssl.create_default_context() # SSL のコンテキストを生成
context.check_hostname = False # ホスト名のチェックを無効化
context.verify_mode = ssl.CERT_NONE # 検証無効化
with urllib.request.urlopen(req, context=context) as res:
body = res.read().decode('utf-8')
print(body)
- POST の場合も同じように
urlopen()
にコンテキストを渡します。
GET (エラー制御)
url = 'https://example.com/'
headers = {
'Accept-Language': 'ja',
}
data = {
'foo': 1
}
try:
req = urllib.request.Request(f'{url}?{urllib.parse.urlencode(data)}', None, headers)
with urllib.request.urlopen(req) as res:
body = res.read().decode('utf-8')
print(body)
except urllib.error.HTTPError as e:
# e.code に数値型でステータスコードが格納されている
print(e)
POST
# import urllib.request
url = 'https://example.com/'
headers = {
'Accept-Language': 'ja',
}
data = {
'foo': 1
}
req = urllib.request.Request(url, urllib.parse.urlencode(data).encode(), headers)
with urllib.request.urlopen(req) as res:
body = res.read().decode('utf-8')
print(body)
POST (JSON)
# import urllib.request
# import json
url = 'https://example.com/'
headers = {
'Content-Type': 'application/json',
}
data = {
'foo': 1
}
req = urllib.request.Request(url, json.dumps(data).encode(), headers)
with urllib.request.urlopen(req) as res:
body = res.read().decode('utf-8')
resData = json.loads(body)
print(resData)
TCP
データの受信 (クライアント側)
# import socket
host = '127.0.0.1'
port = 4000
timeout = 5
with socket.create_connection((host, port), timeout) as sock:
res = sock.recv(1024)
print(repr(res))
# import socket
host = '127.0.0.1'
port = 4000
timeout = 5
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(timeout)
sock.connect((host, port))
res = sock.recv(1024)
print(repr(res))
ログ
ロガーの設定 (コンソール)
# import logging
# import logging.handlers
loglevel = logging.DEBUG # ログレベル
logger = logging.getLogger(__name__) # ロガー生成
logger.setLevel(loglevel) # ログレベル設定
handler = logging.StreamHandler() # 出力ハンドラ (コンソール)
handler.setLevel(loglevel) # ログレベル設定
handler.setFormatter(logging.Formatter(
'%(asctime)s %(name)s [%(levelname)s] %(message)s')) # 出力フォーマット設定
logger.addHandler(handler) # 出力ハンドラのセット
ロガーの設定 (ファイル)
# import logging
# import logging.handlers
loglevel = logging.DEBUG # ログレベル
logger = logging.getLogger(__name__) # ロガー生成
logger.setLevel(loglevel) # ログレベル設定
handler = logging.FileHandler('log.log') # 出力ハンドラ (ファイル)
handler.setLevel(loglevel) # ログレベル設定
handler.setFormatter(logging.Formatter(
'%(asctime)s %(name)s [%(levelname)s] %(message)s')) # 出力フォーマット設定
logger.addHandler(handler) # 出力ハンドラのセット
ロガーの設定 (ファイル + ローテート)
# import logging
# import logging.handlers
loglevel = logging.DEBUG # ログレベル
logger = logging.getLogger(__name__) # ロガー生成
logger.setLevel(loglevel) # ログレベル設定
handler = logging.handlers.TimedRotatingFileHandler('log.log') # 出力ハンドラ (ファイル)
handler.suffix = "%Y%m%d" # ログの後ろにセットする日付フォーマット
handler.setLevel(loglevel) # ログレベル設定
handler.setFormatter(logging.Formatter(
'%(asctime)s %(name)s [%(levelname)s] %(message)s')) # 出力フォーマット設定
logger.addHandler(handler) # 出力ハンドラのセット
ロガーの設定 (設定ファイルから設定)
{
"version": 1,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "custom"
},
"file": {
"class": "logging.handlers.TimedRotatingFileHandler",
"level": "DEBUG",
"filename": "log.log",
"when": "MIDNIGHT",
"formatter": "custom"
}
},
"formatters": {
"custom": {
"format": "%(asctime)s %(name)s [%(levelname)s] %(message)s"
}
},
"root": {
"handlers": ["console", "file"],
"level": "DEBUG"
}
}
# import logging
# import logging.config
# import json
with open('logconfig.json') as f:
config = json.load(f)
logging.config.dictConfig(config)
logger = logging.getLogger(__name__)
ロガーの設定 (設定ファイルから設定 + カスタムハンドラ)
{
"version": 1,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "custom"
},
"file": {
"class": "logging.handlers.CustomTimedRotatingFileHandler",
"level": "DEBUG",
"filename": "log.log",
"when": "MIDNIGHT",
"formatter": "custom"
}
},
"formatters": {
"custom": {
"format": "%(asctime)s %(name)s [%(levelname)s] %(message)s"
}
},
"root": {
"handlers": ["console", "file"],
"level": "DEBUG"
}
}
# import logging
# import logging.config
# import re
# import json
class CustomTimedRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):
"""独自のハンドラクラスです。ファイル形式を log.log.YYYY-MM-DD などから log.YYYYMMDD.log に変更します。
"""
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
logging.handlers.TimedRotatingFileHandler.__init__(self, filename, when, interval,
backupCount, encoding, delay, utc, atTime)
if self.when == 'S':
self.suffix = "%Y%m%d%H%M%S"
elif self.when == 'M':
self.suffix = "%Y%m%d%H%M"
elif self.when == 'H':
self.suffix = "%Y%m%d%H"
elif self.when == 'D' or self.when == 'MIDNIGHT':
self.suffix = "%Y%m%d"
elif self.when.startswith('W'):
self.suffix = "%Y%m%d"
def namer(default_name):
return re.sub(r'log\.([0-9]+)', r'\1.log', default_name)
self.namer = namer
logging.handlers.CustomTimedRotatingFileHandler = CustomTimedRotatingFileHandler
with open('logconfig.json') as f:
config = json.load(f)
logging.config.dictConfig(config)
logger = logging.getLogger(__name__)
ロガーの使用
# logger は上記で作成したロガーです
logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')
try:
raise Exception("exception")
except Exception as e:
logger.exception(e)