« ^ »

今日やった事 - 20240904

所要時間: 約 5分

Emacsのrun-pythonについての理解を深める

run-pythonは、Emacs上でPythonのインタプリタを起動する。関数はlisp/progmodes/python.el.gzで定義されている。引数には、cmd、dedicated、showを渡す事ができる。

起動コマンドには (python-shell-calculate-command) が返した文字列が使われる。この関数は、 python-shell-interpreterpython-shell-interpreter-args からコマンド文字列を組み立てる。

という事は python-shell-interpreter を設定するコマンドを用意すれば、venv内のPythonを使って起動できる。そこで次のような実装を追加してみた。

(defvar python-venv-directory "~/.cache/python-venvs")

(defun python-venv-set-python (venv-directory)
  (interactive (list (read-directory-name
		      "venv dir: " python-venv-directory)))
  (setq python-shell-interpreter
	(format "%s/bin/python" venv-directory)))

pytzでタイムゾーンオブジェクトを作る

import pytz

pytz.timezone("Asia/Tokyo")

pytz.timezoneは内部で pytz.tzfile.build_tzinfo() を呼び出す。この関数は、タイムゾーン情報のファイルを読み出し、ZoneInfoオブジェクトを生成して返す。

タイムゾーン情報のファイルは、 pytz/zoneinfo/ ディレクトリ配下に保持している。このファイルは決めらてた形式のバイナリファイルとなっており、それをstructモジュールを使って読み出している。pytz.tzfile.build_tzinfo()は、その読み出しのためのフォーマット文字列の組み立ても行っている。

ヘッダーのフォーマットは >4s c 15x 6l 、サイズは44バイトだ。データのフォーマットは >9l 9B lBBlBBlBBlBB 12s 、サイズは81バイトだ。これ、何のフォーマットなのだろう。

最終的に以下のようにクラスを作成し、それをインスタンス化している。

cls = type(zone, (DstTzInfo,), {...})
return cls()

おそらく時刻情報が増えた時に対応するためなのだろうけれど、なぜこんなに面倒な実装にしたのだろうか。機会があれば、なぜこうしたのか聞いてみたい。

<DstTzInfo 'Asia/Tokyo' LMT+9:19:00 STD>

この LMT は、Local Mean Timeの略で地方平均時の事だ。

https://ja.wikipedia.org/wiki/%E5%9C%B0%E6%96%B9%E5%B9%B3%E5%9D%87%E6%99%82

実際に使いたいのは、 JST でこれは日本標準時だ。この二つは異なる時刻系であり、その変換を間違った方法で行うために、時間のズレが生じてしまうようだ。

時刻系についても勉強してみたいけれど、今回はあまり深追いしないでおく。

https://ja.wikipedia.org/wiki/%E6%99%82%E5%88%BB%E7%B3%BB

datetime.datetimeオブジェクトのastimezone()を使用する場合、内部ではreplaceを使っている。

Pythonでは、時刻情報にタイムゾーン情報がないものと、あるものがあり、ないものをナイーブ、あるものをアウェアと呼び区別する。その時刻情報がアウェアである条件は公式のドキュメント「」に明記されている。 https://docs.python.org/ja/3/library/datetime.html#determining-if-an-object-is-aware-or-naive

そこには、こうある。

  1. d.tzinfoNone でない
  2. d.tzinfo.utcoffset(d)None を返さない

    これを確認してみよう。

    >>> naive = datetime.datetime.now()
    >>> naive.tzinfo
    >>> tz_jp = pytz.timezone("Asia/Tokyo")
    >>> tz_jp
    <DstTzInfo 'Asia/Tokyo' LMT+9:19:00 STD>
    >>> aware = naive.astimezone(tz_jp)
    >>> aware
    datetime.datetime(2024, 9, 4, 19, 32, 59, 128833, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
    >>> aware.tzinfo
    <DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>
    >>> aware.tzinfo.utcoffset(aware)
    datetime.timedelta(seconds=32400)
    >>> aware.tzinfo.utcoffset(naive)
    datetime.timedelta(seconds=32400)
    

pytz.timezone("Asia/Tokyo") で取得したタイムゾーンは LMT+9:19:00 となっていた。しかし、 naive.astimezone(tz_jp) でタイムゾーン情報を追加したawareオブジェクトの属性として付いているタイムゾーン情報は JST+9:00:00 となっていた。この変換がどこで行なわれているのか全く分からないけれど、このあたりがズレの原因だろう。

pytzは、過去に何度かあったタイムゾーンの取り扱いの変更や、夏時間の情報などを全て記録しているため、このズレが起きるのだが、僕はこの「過去に何度かあったタイムゾーンの取り扱いの変更」の部分を調べたいのだろう。あのバイナリファイルにあるのかもしれないが、なかなか見えてこない。

Emacsでバックアップファイルを作成しないようにする

(setq make-backup-files nil)

記録できなかった事を引き継ぐ

(注意: この文章はChatGPTによって生成した)

僕たちは日々、無数の思いや経験を積み重ねて生きている。しかし、作業という名の思い出をすべて完璧にこなし、記録していく事はは難しい。それでも、その一つ一つが僕たちの成長や未来の自分へのメッセージとなり得る。だから、それらを手元に置いておきたいと思った。

技術は進化し、僕たちは多くのものをデジタルに記録する。その中でも、リビジョンを管理するツールは強力だ。そして、今はGitが主流と言える。開発者にとっては自分や他人の手によるコードの変遷を追跡し理解する助けとなるし、開発者でなくとも利用する価値はある。

テキストなど記録できるものは、全てGitコミットするという習慣をつけることが重要だ。それはコードだけでなく、アイデアやメモ、試行錯誤の過程を含むものもそうだ。このようにして、僕たちは過去の自分との対話を深め、さらに未来の自分に対する贈り物として記録を残す事ができる。

日常生活や仕事の中で、どんなに小さな事でも「今日やった事」を記録する習慣を持つことは非常に有益である。これらの記録は、記事のディレクトリにまとめることで、過去の自分が経験したことを俯瞰的に見ることができる。これらを実践し、昨日の自分が未来の自分に託した思いを引き継ぎ、堅実な一歩を踏み出せるようにしたい。記録の積み重ねが自分自身の成長の架け橋となり、未来へと続いていくのである。

記録、整理、フィードバックのプロセスを日常的に取り入れることで、僕たちは過去と未来の自分をつなぐことができる。このプロセスは、技術だけでなく、個々の成長にもつながる。記録できなかった思い出や経験も、適切な形で未来へと引き連れていくことができるのである 。