ablog

不器用で落着きのない技術者のメモ

Pythonメモ

コード

実行中のスクリプト名を取得する
  • コード
import os
print os.path.basename(__file__)
コメントアウト
  • コード
# 1行コメントアウト

"""
複数行の
コメントアウト
"""
データ型を確認する
  • コード
list=[1,2,3]
print(type(list))
環境変数を取得する
  • コード
import os
host=os.environ['RS_HOST']
現在時刻を取得する
  • コード
import datetime
print('{0:%Y-%m-%d %H:00:00}'.format(now))
  • 実行結果
2020-04-25 08:00:00
時刻でマイクロ秒の表示
  • %Y: 年(4桁)
  • %y: 年(2桁)
  • %m: 月
  • %d: 日
  • %H: 時
  • %M: 分
  • %S: 秒
  • %f: マイクロ秒
  • %A: 曜日
  • %a: 曜日(短縮形)
  • %w: 曜日(数値: 0-6, 0:日曜日, 1:月曜日, … 6:土曜日)
Pythonのdatetimeでformat指定する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
時刻の加算・減算
  • コード
    • 1時間減算
now = datetime.datetime.now()
begin_time='{0:%Y-%m-%d %H:00:00}'.format(now - datetime.timedelta(hours=1))
文字列の左0埋め
  • コード
dt_now = datetime.now()
year = dt_now.year
month = dt_now.month
day = dt_now.day
path="dir/to/{0}/{1:0=2}/{2:0=2}/".format(year, month, day),
パスからファイル名を取り出す
  • コード
basename = os.path.basename(filepath)
print(basename)
# filename.ext
Pythonでパス文字列からファイル名・フォルダ名・拡張子を取得、結合 | note.nkmk.me
ディレクトリがないときは再帰的に作成する

引数exist_okがある場合
Python 3.2以降は引数exist_okが追加されており、exist_ok=Trueとすると既に末端ディレクトリが存在している場合もエラーが発生しない。末端ディレクトリが存在していなければ新規作成するし、存在していれば何もしない。前もって末端ディレクトリの存在確認をする必要がないので便利。

os.makedirs('exist_dir/exist_dir', exist_ok=True)

引数exist_okがない場合
Pythonのバージョンが古くos.makedirsに引数exist_okがない場合は、先にos.path.existsで末端ディレクトリの有無を判定して条件分岐すれば、末端ディレクトリが存在しない場合のみ新規に作成するようにできる。

if not os.path.exists('exist_dir/exist_dir'):
    os.makedirs('exist_dir/exist_dir')
Pythonで深い階層のディレクトリを再帰的に作成するmakedirs | note.nkmk.me
gzip で圧縮されたファイルを直接読む
import gzip

with gzip.open('test.txt.gz', mode='rt', encoding='utf-8') as f:
    data = f.read()

print(data.split('\n')[1])
Pythonでgzip圧縮されたファイルからデータを直接読み込む — 某エンジニアのお仕事以外のメモ(分冊)
ディクショナリから一部のキーに絞ったディクショナリを作成する
  • コード
# ディクショナリの全キー
['logTime', 'statementId', 'substatementId', 'objectType', 'command', 'objectName', 'databaseName', 'dbUserName', 'remoteHost', 'remotePort', 'sessionId', 'rowCount', 'commandText', 'paramList', 'pid', 'clientApplication', 'exitCode', 'class', 'serverVersion', 'serverType', 'serviceName', 'serverHost', 'netProtocol', 'dbProtocol', 'type', 'startTime', 'errorMessage']
# 抽出するキー
fieldnames = ['logTime', 'serverHost', 'remoteHost', 'databaseName', 'serviceName', 'dbUserName', 'clientApplication', 'commandText', 'rowCount']
filtered_fieldnames = dict(filter(lambda x: x[0] in fieldnames, json_dict.items()))
イベントループを使った並行処理
__future__モジュールとは

__future__モジュールとは
Python2系にデフォルトで入っており、Python3で実装された互換性のない機能をPython2系で利用できるようにするモジュール。つまり、Python2系で、3系の書き方をできるようにするモジュール。
Python2系から3系に移行する際に、一時的に2系でも3系でも動くコードにしたい場合の一時対策として、必要であれば利用するのが望ましい。

【Python2to3アップデート方法】Python2系と3系の違い - Qiita
asyncio.gather で同じ関数を指定した並行度で実行する
statements = []

statements.append(test("hello world"))
# ...

results = await asyncio.gather(*statements)

パッケージのバージョンを表示する

  • コード
import six as s
print(s.__version__)
  • 標準出力
1.13.0
if __name__ == "__main__"

ですので、 if __name__ == "__main__" という if文を使うことで、「この hello.py は python hello.py のように実行された(== importされたことで動作したのではない)」と判定できます。

if __name__ == '__main__':
    ...
Pythonのif __name__ == "__main__" とは何ですか?への回答 - Python学習チャンネル by PyQ
ディレクトリがなかったら作成する
  • コード
import os

if not os.path.isdir(download_dir):
    os.makedirs(download_dir)
リストでループする
  • コード
list = ['a','b','c','d']
for item in list:
    print(item)
条件を満たすまでループする
  • コード
start_date = '2020-06-01'
end_date = '2020-06-30'

date_dt = datetime.datetime.strptime(start_date, '%Y-%m-%d')
end_date_dt = datetime.datetime.strptime(end_date, '%Y-%m-%d')

while True:
    date_str = date_dt.strftime('%Y-%m-%d')
    date_dt = date_dt + datetime.timedelta(days=1)
    if date_dt > end_date_dt:
        break
日付を加算する
  • コード
start_date = '2020-06-01'
date_dt = datetime.datetime.strptime(start_date, '%Y-%m-%d')
# 1日加算
date_dt = date_dt + datetime.timedelta(days=1)
文字列を日付に変換
  • コード
start_date = '2020-06-01'
date_dt = datetime.datetime.strptime(start_date, '%Y-%m-%d')
# 1日加算
date_dt = date_dt + datetime.timedelta(days=1)
例外を表示する
  • コード
except:
    import traceback
    traceback.print_exc()
  • 参考:

python - pythonですべての例外をキャッチし、詳細を表示させたい。 - スタック・オーバーフロー

コマンドライン引数を扱う
  • コード
import argparse

parser = argparse.ArgumentParser(description='Scraping hatena blog and get title and url list') 
parser.add_argument('arg1', help='YYYY(Year of the articles)')
parser.add_argument('arg2', help='MM(Month of the articles)')
parser.add_argument('arg3', help='99(e.g. 3 means 3 months)')
args = parser.parse_args()

year = args.arg1
month = args.arg2
period = args.arg3
$ python hatena_scraper.py 2020 10 3 > 2020Q4
$ python hatena_scraper.py
usage: hatena_scraper.py [-h] arg1 arg2 arg3
hatena_scraper.py: error: the following arguments are required: arg1, arg2, arg3
$ python hatena_scraper.py -h
usage: hatena_scraper.py [-h] arg1 arg2 arg3

Scraping hatena blog and get title and url list

positional arguments:
  arg1        YYYY(Year of the articles)
  arg2        MM(Month of the articles)
  arg3        99(e.g. 3 means 3 months)

optional arguments:
  -h, --help  show this help message and exit
月の足し算
  • コード
# 文字列で日付を指定
string_date =  '2020-10-01'
# 型変換
article_date = datetime.datetime.strptime(string_date, '%Y-%m-%d')
# 1月加算する
article_date = article_date + relativedelta(months=1)
# 年月を表示
print(article_date.year)
print(article_date.month)
dict の全要素の型を変換する
  • コード
casted_row = dict(map(lambda cols: map(str, cols), rows[i].items()))
数値と文字列を連結して標準出力
  • コード
num1 = 8
num2 = 6
print(str(num1) + "+" + str(num2) + "=" + str(num1 + num2))
リストでループ(インデックスを使いたいケース)
  • コード
list1 = ['item1', 'item2', 'item3']
for index in range(len(list1)):
    print("インデックス:" + str(index) + ", 値:" + list1[index])

pip

whl ファイルをインストールする
  • コマンド
$ pip install python_dateutil-2.6.1-py2.py3-none-any.whl
Processing ./python_dateutil-2.6.1-py2.py3-none-any.whl
Requirement already satisfied: six>=1.5 in ./.pyenv/versions/3.6.9/lib/python3.6/site-packages (from python-dateutil==2.6.1) (1.5.0)
Installing collected packages: python-dateutil
Successfully installed python-dateutil-2.6.1
バージョンを指定してインストールする
  • コマンド
$ pip install six==1.5.0
Collecting six==1.5.0
  Downloading https://files.pythonhosted.org/packages/ca/15/e62a66024dded9640f8d39112330e6b108e7ab21a1b8618c2d1e2eea7e1d/six-1.5.0-py2.py3-none-any.whl
Installing collected packages: six
Successfully installed six-1.5.0
アンイストール
  • コマンド
$ pip uninstall python_dateutil
Uninstalling python-dateutil-2.8.1:
  Would remove:
    /home/ec2-user/.pyenv/versions/3.6.9/lib/python3.6/site-packages/dateutil/*
    /home/ec2-user/.pyenv/versions/3.6.9/lib/python3.6/site-packages/python_dateutil-2.8.1.dist-info/*
Proceed (y/n)? y
  Successfully uninstalled python-dateutil-2.8.1