今回Pythonでカレンダーを作成しました。
calendarモジュールは使わず、月指定をするのにコマンドラインで引数を入力する必要があったので、標準ライブラリのsysモジュールを使用しました。
sysというものを初めて使用したので考えを整理するためにまとめてみました。
動作環境:Python 3.13.5
Pythonのsysモジュール
Pythonのsysモジュールは、インタプリタや実行環境に関する情報や機能を提供する標準ライブラリです。sysはsystemの略です。
インタプリタ: 1行ずつ機械がわかる言葉に変換していく方法
標準ライブラリのため、使用する際はimport sys
と書けば使用できます。
なぜsysモジュールを今回importしたか
カレンダーを作成するにあたり、月指定をするのにコマンドラインで引数を入力する必要があったため
今回使用したsysの機能
sys.argv:
コマンドライン引数をリストとして取得する
sys.exit():
Pythonインタプリタを終了する。正常終了時に使用
今回作成したコード
今回、カレンダーを作成するにあたって書いたコードを使って解説します。
import datetime
import sys
from datetime import date, timedelta
def get_last_day_of_month(year, month):
if month == 12:
next_month_first = datetime.datetime(year + 1, 1, 1)
else:
next_month_first = datetime.datetime(year, month + 1, 1)
return (next_month_first - timedelta(days=1)).day
def display_calendar(year, month):
print(f" {month}月 {year}")
weekday_names = ['月', '火', '水', '木', '金', '土', '日']
print(' '.join(weekday_names))
first_date = date(year, month, 1)
first_weekday = first_date.weekday()
for _ in range(first_weekday):
print(" ", end='')
last_day = get_last_day_of_month(year, month)
for day in range(1, last_day + 1):
print(f"{day:2d} ", end='')
if (first_weekday + day - 1) % 7 == 6:
print()
if (first_weekday + last_day - 1) % 7 != 6:
print()
today = datetime.datetime.now()
year, month = today.year, today.month
if len(sys.argv) == 1:
pass
elif len(sys.argv) == 3:
_, option, value = sys.argv
if option == "-m":
try:
month = int(value)
if month < 1 or month > 12:
print(f"{month} is neither a month number (1..12) nor a name")
sys.exit(1)
except ValueError:
print(f"{value} is neither a month number (1..12) nor a name")
sys.exit(1)
display_calendar(year, month)
その内、こちらがsysを使用した箇所です。
if len(sys.argv) == 1:
pass
elif len(sys.argv) == 3:
_, option, value = sys.argv
if option == "-m":
try:
month = int(value)
if month < 1 or month > 12:
print(f"{month} is neither a month number (1..12) nor a name")
sys.exit(1)
except ValueError:
print(f"{value} is neither a month number (1..12) nor a name")
sys.exit(1)
sys.argvについて
sys.argvに引数が何個入っているかによって条件が変わるようになっています。
コマンドラインに何も入力せずに、こちらのコードを実行した場合は実行した月のカレンダーが表示されます。
その際sys.argvに入っている引数は1です。
以下のコードを実行すると引数が1になっているのがわかります。
print('sys.argv : ', sys.argv)
print('type(sys.argv) : ', type(sys.argv))
print('len(sys.argv) : ', len(sys.argv))
実行結果
sys.argv : ['/Users/ow/python/python_calendar.py']
type(sys.argv) : <class 'list'>
len(sys.argv) : 1
sys.argv
について上にコマンドライン引数をリストとして取得する
と書いた通りにリストで取得しているのがわかります。引数の数もひとつです。
※こちらの方法は分かりやすかったのでnote.nkmk.meというサイトを参考にさせていただきました。
Pythonでコマンドライン引数を扱う方法(sys.argv, argparse)
引数がひとつの場合はif文の最初に該当するのでそのまま実行されます。
if len(sys.argv) == 1:
pass
次に
python3 python_calendar.py -m 12
で実行した内容を確認します。
sys.argv : ['python_calendar.py', '-m', '12']
type(sys.argv) : <class 'list'>
len(sys.argv) : 3
リストの中の引数が3になっていて引数のsys.argv[1]が'-m'になっているので、下記のコードの中のtryかexcptが実行されると判断できます。
elif len(sys.argv) == 3:
_, option, value = sys.argv
if option == "-m":
try:
month = int(value)
if month < 1 or month > 12:
print(f"{month} is neither a month number (1..12) nor a name")
sys.exit(1)
except ValueError:
print(f"{value} is neither a month number (1..12) nor a name")
sys.exit(1)
このようにsys.argvを使用することによって、コマンドラインで月を指定できるようになりました。
sys.exit()について
インタプリタを終了してくれます。
例えばpython3 python_calendar.py -m 121
と入力した際に、エラーメッセージが出力されてそこでストップします。
121 is neither a month number (1..12) nor a name
# このエラーメッセージのみ表示してストップ
sys.exit()がないと、インタプリタが止まらず実行され続けクラッシュします。
121 is neither a month number (1..12) nor a name
121月 2025
月 火 水 木 金 土 日
Traceback (most recent call last):
File "/Users/ow/python/python_calendar.py", line 58, in <module>
display_calendar(year, month)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "/Users/ow/python/python_calendar.py", line 21, in display_calendar
first_date = date(year, month, 1)
ValueError: month must be in 1..12
想定外の引数が入力された際に、プログラムを止めてクラッシュするのを防いでくれます。