Yearly Archives: 2022

2022-04-06

Windows上のEmacs 28.1でNative Compilationを使う

(2025-02-24追記: Emacs 30.1での設定はこちら)

(2024-02-19追記: 手っ取り早く使い方を知りたい人はMS-Windows版 Emacs 29.1への移行作業をご覧下さい)

Emacs 28.1がリリースされましたね。私は少し前にpretestをいじりましたがすぐに27.2に戻ったので28系を本格的に使うのはようやくこれからです。

Windows版が見当たらないので自分でビルドしようかなーと思っていたらすぐにアップロードされたのでそれ(emacs-28.1.zip)をダウンロードして試してみました。

Emacs 28と言えば大分前からネイティブコンパイルという単語をあちこちで見かけていました。WindowsでGCCに依存した機能って大変なんじゃないの? と思っていたので期待はしていなかったのですが、一応どうなっているのか調べてみることにしました。

Native Compilation (GNU Emacs Lisp Reference Manual)

ええと何々

Emacsのカレントプロセスでネイティブコンパイル済みLispコードの生成およびロードが可能かどうか判断するには、native-comp-available-p (Native-Compilation Functionsを参照)を呼び出してください。

(native-comp-available-p)
nil

あー、やっぱり……。そもそも emacs-28.1.zip の中にGCCなんて入ってないですもんね。

ええと、ネイティブコンパイル機能はlibgccjitを利用していてビルド時に --with-native-compilation の指定が必要。MSYS2にはlibgccjitパッケージもちゃんとあるんですね。

仕方ない、ビルドしますか。以前ビルドした時のMSYS2環境が残っていますし。MSYS2のEmacsパッケージ(mingw-w64-x86_64-emacs)もまだ27.2みたいですし。

MSYS2でEmacs 28.1のビルド

(2022-04-07追記: 公式配布のWindows版はどうやら --with-native-compilation 付きでビルドされているようです。ただし必要なDLLが含まれていないので (native-comp-available-p)nil になります。MSYS2のmingw64/bin/libgccjit-0.dllをEmacsのbinへコピーするかmingw64/binへPATHを通したら (native-comp-available-p)t になりました。なので以下のビルドはしなくても行けます。ただしmingw64/binへ常にPATHを通したくない場合は色々と調整する必要があります(後述))

nt/INSTALLnt/INSTALL.W64等を見るにビルド方法に大きな変更は無さそうです。

まずはMSYS2から既存パッケージのアップグレード(sourceforgeのミラーが廃止されたんですね。/etc/pacman.d以下を少し修正)。

その後今回追加で必要になるであろうmingw-w64-x86_64-libgccjitをインストール。

pacman -S mingw-w64-x86_64-libgccjit

次にMinGW64環境からビルド。 --without-dbus--with-gnutls は前にビルドした時に付けていたので一応。今も必要なのか不明。 --with-native-compilation は無いとダメだったので付けました。 --prefix にはインストール先を明示的に指定します。後でMinGW64環境と分離したいので。

mkdir 20220406 && cd 20220406
wget https://ftp.gnu.org/gnu/emacs/emacs-28.1.tar.gz
tar xvfz emacs-28.1.tar.gz
./configure --without-dbus --with-gnutls --with-native-compilation --prefix=/c/hogehoge/emacs-28.1
make -j4 #4はコア数
make install-strip
/c/hogehoge/emacs-28.1/bin/runemacs.exe -Q # 試しに起動
(native-comp-available-p)
t

うん、大丈夫っぽい。というか裏で自動的にコンパイルが走っててキモいんですけど(笑)

MSYS2 MinGW環境からの分離

次にMSYS2 MinGW環境以外からでも単独で起動できるように必要なDLL等をemacsのディレクトリへコピーします。

これで runemacs.exe をエクスプローラ等から直接実行しても起動するようになりますが……やはりネイティブコンパイルでエラーが出まくります。libgccjitがGCCを見つけられないのですから当たり前ですよね。というかCygwinのが起動されてるっぽい? ldがライブラリが見つからないとか言ってます。私はCygwinの方にはPATHを通してしまっていますからね。Cygwinのldが起動されて、それがMinGWのライブラリが見つけられないという流れになってしまっているのかもしれません。

Internals — libgccjit 12.0.1 (experimental ) documentation あたりを見ると、PATH、LIBRARY_PATHあたりの環境変数をちゃんとすれば何とかなりそう。

試しに (setenv "PATH" (concat "c:/hogehoge/msys/mingw64/bin;" (getenv "PATH"))) を評価してPATHの先頭にMinGWのbinを追加したところコンパイルが成功するようになりました。

うーん、でも常時MinGWにPATHを通したくないんだよなぁ……。

native-comp-async-env-modifier-form という変数があったので、そこで環境変数を設定してみるもうまくいかず。

ネイティブコンパイルは外部のemacsを起動して行う(コンパイル用のelファイルを生成して、 emacs --batch -l ????.el を起動する)みたいなので、その起動時にだけ環境変数を追加することにしました。

(when (and (fboundp #'native-comp-available-p)
           (native-comp-available-p))
  (defun my-comp-set-env (orig-fun &rest args)
    (let ((process-environment
           (append
            (list (concat "PATH=c:/hogehoge/msys/mingw64/bin;" (getenv "PATH"))
                  ;;"LIBRARY_PATH=c:/hogehoge/msys/mingw64/lib" 不要っぽい
                  )
            process-environment)))
      (apply orig-fun args)))

  (require 'comp)
  (advice-add #'comp-final :around #'my-comp-set-env) ;; call-processでemacsを起動している
  (advice-add #'comp-run-async-workers :around #'my-comp-set-env)) ;;make-processでemacsを起動している

適当ですがとりあえず。これで直接runemacs.exeを起動したとき(PATHにmingw64/binが含まれていないとき)でもネイティブコンパイルが成功するようになりました。

で、 ~/.emacs.d/eln-cache/ に色々ファイルが生成されているわけですが、これってちゃんと使われているのでしょうか。スピードも上がっているのでしょうか。後で調べてみようっと。

(2022-04-08追記:)

28.0.91(pretest)のWindows用バイナリが出たときのredditの投稿に、参考になることが色々書いてありました。

alpha.gnu.org has shiny new Emacs 28.0.91 Windows binaries : emacs

中でも、MSYS2から17ファイルほどコピーすればMSYS2無しでもネイティブコンパイルが出来るのだとか。

  • bin/libgccjit-0.dll
  • lib/gcc/crtbegin.o
  • lib/gcc/crtend.o
  • lib/gcc/dllcrt2.o
  • lib/gcc/libadvapi32.a
  • lib/gcc/libgcc.a
  • lib/gcc/libgcc_s.a
  • lib/gcc/libkernel32.a
  • lib/gcc/libmingw32.a
  • lib/gcc/libmingwex.a
  • lib/gcc/libmoldname.a
  • lib/gcc/libmsvcrt.a
  • lib/gcc/libpthread.a
  • lib/gcc/libshell32.a
  • lib/gcc/libuser32.a
  • libexec/emacs/28.0.91/x86_64-w64-mingw32/ld.exe
  • libexec/emacs/28.0.91/x86_64-w64-mingw32/as.exe

MSYS2の中からファイルを探してemacs-28.1.zipを展開したディレクトリ下の上記の場所にコピーして試したところ、確かに関数の同期コンパイルくらいは出来ているように見えます(私のPCはCygwinのldにPATHが通ってたりするので、他のPCで再現しない可能性あり。後でちゃんと確認します)。非同期のコンパイルはPATHを調整しないとダメだとも書いてあります。

後でもう少し詳しく調べて追記します。

(2022-04-11追記: 別の記事として書きました)

Windows上のEmacs 28.1でネイティブコンパイルする方法(まとめ)

2022-04-06

Windows上のEmacsでSVG画像内のimage要素が表示されない問題

Emacs27になってからSVG画像内のimage要素が表示されなくて困ったのですが、調べたところ lib/gdk-pixbuf-2.0/2.10.0/loaders.cache ファイルが無いのが原因だと分かりました。

いずれも Index of /gnu/emacs/windows にある公式のWindows版ビルドでの話です。独自ビルドして必要そうなDLLファイルをMinGWから抜き出した場合も起こるかもしれません。

表示されないSVGの例

例えば次のようなSVGでimage要素の部分が表示されずblueのrectだけが表示されます。

<svg width="400" height="300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect x="10px" y="10px" width="100px" height="80px" fill="blue" />
  <image xlink:href="image1.jpg" x="20px" y="20px" width="100px" height="100px" />
  <image xlink:href="image2.png" x="30px" y="30px" width="100px" height="100px" />
  <image xlink:href="image3.bmp" x="40px" y="40px" width="100px" height="100px" />
</svg>

image1.jpgimage2.pngimage3.bmp はSVGと同じディレクトリにあるものとします。もちろんブラウザ等、他のソフトウェアでは正しく表示されます。Emacsでの確認方法は色々ありますがdiredから開くだけでも十分です。

Emacs 26.3の場合

https://ftp.gnu.org/gnu/emacs/windows/emacs-26/emacs-26.3-x86_64.zip

問題は起きません。正しく表示されます。

Emacs 27.2の場合

解決方法

cmdプロンプトで emacs-27.2-x86_64/bin ディレクトリへ移動し、次のコマンドを実行すると emacs-27.2-x86_64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache というファイルが生成されます。

gdk-pixbuf-query-loaders.exe --update-cache

Emacsを再起動して再び試してみると正しく表示されました。

Emacs 28.1の場合

https://ftp.gnu.org/gnu/emacs/windows/emacs-28/emacs-28.1.zip

image要素が表示されません。

解決方法

そもそも emacs-28.1/lib/ 以下に gdk-pixbuf-2.0 がありません。

Emacs27のファイル(emacs-27.2-x86_64/lib/gdk-pixbuf-2.0 以下。もちろん loaders.cache も)をEmacs28へコピーしたところ正しく表示されました。

loaders.cache を削除すると正しく表示されないので、Emacs28でもこのファイルは必要なようです。 emacs-28.1.zip には gdk-pixbuf-query-loaders.exe が含まれていないので、生成するにはEmacs 27の場合の手順を踏んでそちらからコピーしてくるのが手っ取り早いと思います。

原理

EmacsはSVGの描画にlibrsvgを使用していますが、librsvgは画像の処理にlibgdk_pixbufを使用しています。

libgdk_pixbufで画像を読み込むには画像の形式に対応するローダーライブラリが必要で、それが lib/gdk-pixbuf-2.0/2.10.0/loaders/ 以下にあるDLLファイル群です。

loaders.cache ファイルには、DLLファイルへのパスとそれが受け付けるMIMEタイプ、拡張子、ファイル先頭のマジックナンバー等の対応表が記されているようです。詳しくは調べていませんが、このファイルが無いとlibgdk_pixbufは画像を読み込めないようです。

不思議なことにEmacs26はこのファイルが無くても正しく読み込めていました。おそらくライブラリのバージョンアップに伴って必要になったのではないでしょうか。

必要性

EmacsでSVG内のimage要素、それもWindowsで扱う必要がある人はどれだけいるのでしょうか。多分ほとんどの人が問題に気がついていないのだと思います(まさか私の環境だけ起きてる?)。

しかしsvg.elにはsvg-embedのようなimage要素を使う機能も存在します。

また、Emacs28ではSVG内のimage要素が外部ファイルを参照する時の基準ディレクトリを指定する機能も追加されました。(https://github.com/emacs-mirror/emacs/blob/78ecd67888566167fb4c881d8350f611fa039649/etc/NEWS.28#L2417 )

図形だけでも面白いのに画像を自由に配置できるとなればもっと面白いことが色々出来るはずです。皆さんも是非試してみてはいかがでしょうか。

私も試しにimage要素を沢山生成して遊んでみました。

2022-04-06-svg-image-ex.gif

一枚一枚の画像をtransform属性で変形し(残念ながら透視投影は無理なので正射影です)、面単位でZソートを行っています。

結構遅いです。

何となくEmacs Lisp側というよりは描画ライブラリ側が遅いような気が。

2022-02-26

Emacsからアメダス観測所の計測データを取得する

前回の続き

一応任意のアメダス観測所の計測データを取得できるようにしてみました。あまり使う予定はありませんが。

misohena/el-jma: Emacs Interface for Japan Meteorological Agency Data

使い方。

まずはアメダスの観測所番号を調べます。 jma-amedas-read-amedas-code 関数で補完付きの入力ができるようになっているのでそれを使います。

(require 'jma-amedas)
(jma-amedas-read-amedas-code)

番号が分かったら jma-amedas-point-latest に渡すだけです。

(jma-amedas-point-latest ;;最新のデータを取得
 "44112");;八王子

結果は次のようになります。

(\20220226141000
 (prefNumber . 44)
 (observationNumber . 112)
 (temp .
       [12.6 0])
 (sun10m .
         [10 0])
 (sun1h .
        [1.0 0])
 (precipitation10m .
                   [0.0 0])
 (precipitation1h .
                  [0.0 0])
 (precipitation3h .
                  [0.0 0])
 (precipitation24h .
                   [0.0 0])
 (windDirection .
                [7 0])
 (wind .
       [8.8 0])
 (maxTempTime
  (hour . 4)
  (minute . 41))
 (maxTemp .
          [13.4 0])
 (minTempTime
  (hour . 20)
  (minute . 22))
 (minTemp .
          [-2.7 0])
 (gustTime
  (hour . 4)
  (minute . 58))
 (gustDirection .
                [8 0])
 (gust .
       [15.2 0]))

一応アクセッサがあるのでそれを使うと楽にデータを取り出せます。

(let* ((amedas-code "44112")
       (sample (jma-amedas-point-latest amedas-code)))
  (format "%sの%sの気温は%s℃、降水量(前1時間)は%smmです"
    (jma-amedas-point-name (jma-amedas-point amedas-code))
    (format-time-string "%Y-%m-%d %H:%M" (jma-amedas-sample-time sample))
    (or (jma-amedas-sample-temp sample) "-")
    (or (jma-amedas-sample-precipitation1h sample) "-")))
"八王子の2022-02-26 14:10の気温は12.6℃、降水量(前1時間)は0.0mmです"

取り出せる情報は設備の種類によって異なります(気象庁 | アメダスあたりを参照のこと)。

また、計測値の品質に問題がある場合はnilを返します。生データの配列(上の例だと(temp . [12.6 0])等)の二番目の要素が品質を示す値で、0のとき正常を意味します。

期間を指定して取得することも可能です。

(let* ((max-time (jma-amedas-latest-time))
       (min-time (time-add max-time (* -5 60 60))))
  (jma-amedas-point-samples-between "44112" min-time max-time))
((\20220226093000 (prefNumber . 44) (observationNumber . 112) (temp . [9.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [1.0 0]) (maxTempTime (hour . 0) (minute . 27)) (maxTemp . [9.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 20) (minute . 31)) (gustDirection . [13 0]) (gust . [4.4 0]))
 (\20220226094000 (prefNumber . 44) (observationNumber . 112) (temp . [9.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [4 0]) (wind . [1.5 0]) (maxTempTime (hour . 0) (minute . 40)) (maxTemp . [9.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 20) (minute . 31)) (gustDirection . [13 0]) (gust . [4.4 0]))
 (\20220226095000 (prefNumber . 44) (observationNumber . 112) (temp . [10.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [5 0]) (wind . [2.3 0]) (maxTempTime (hour . 0) (minute . 46)) (maxTemp . [10.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 50)) (gustDirection . [7 0]) (gust . [5.4 0]))
 (\20220226100000 (prefNumber . 44) (observationNumber . 112) (temp . [10.3 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.6 0]) (maxTempTime (hour . 0) (minute . 56)) (maxTemp . [10.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 58)) (gustDirection . [8 0]) (gust . [5.8 0]))
 (\20220226101000 (prefNumber . 44) (observationNumber . 112) (temp . [10.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [3.1 0]) (maxTempTime (hour . 0) (minute . 56)) (maxTemp . [10.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 0) (minute . 58)) (gustDirection . [8 0]) (gust . [5.8 0]))
 (\20220226102000 (prefNumber . 44) (observationNumber . 112) (temp . [10.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.0 0]) (maxTempTime (hour . 1) (minute . 15)) (maxTemp . [10.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226103000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.2 0]) (maxTempTime (hour . 1) (minute . 29)) (maxTemp . [11.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226104000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [3.1 0]) (maxTempTime (hour . 1) (minute . 39)) (maxTemp . [11.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226105000 (prefNumber . 44) (observationNumber . 112) (temp . [10.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [3.0 0]) (maxTempTime (hour . 1) (minute . 39)) (maxTemp . [11.7 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226110000 (prefNumber . 44) (observationNumber . 112) (temp . [11.2 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [3.6 0]) (maxTempTime (hour . 1) (minute . 58)) (maxTemp . [11.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226111000 (prefNumber . 44) (observationNumber . 112) (temp . [11.5 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.5 0]) (maxTempTime (hour . 1) (minute . 58)) (maxTemp . [11.8 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226112000 (prefNumber . 44) (observationNumber . 112) (temp . [11.5 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [9 0]) (wind . [2.8 0]) (maxTempTime (hour . 2) (minute . 14)) (maxTemp . [12.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226113000 (prefNumber . 44) (observationNumber . 112) (temp . [11.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [2.6 0]) (maxTempTime (hour . 2) (minute . 14)) (maxTemp . [12.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226114000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.4 0]) (maxTempTime (hour . 2) (minute . 40)) (maxTemp . [12.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226115000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [9 0]) (wind . [3.0 0]) (maxTempTime (hour . 2) (minute . 50)) (maxTemp . [12.9 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 1) (minute . 13)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226120000 (prefNumber . 44) (observationNumber . 112) (temp . [12.7 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [4.0 0]) (maxTempTime (hour . 2) (minute . 55)) (maxTemp . [13.0 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 0)) (gustDirection . [8 0]) (gust . [7.5 0]))
 (\20220226121000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [4.9 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 6)) (gustDirection . [7 0]) (gust . [8.3 0]))
 (\20220226122000 (prefNumber . 44) (observationNumber . 112) (temp . [12.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [6 0]) (wind . [5.1 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 6)) (gustDirection . [7 0]) (gust . [8.3 0]))
 (\20220226123000 (prefNumber . 44) (observationNumber . 112) (temp . [12.1 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.1 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0]))
 (\20220226124000 (prefNumber . 44) (observationNumber . 112) (temp . [12.3 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [5.5 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0]))
 (\20220226125000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.8 0]) (maxTempTime (hour . 3) (minute . 3)) (maxTemp . [13.1 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 21)) (gustDirection . [9 0]) (gust . [9.7 0]))
 (\20220226130000 (prefNumber . 44) (observationNumber . 112) (temp . [12.5 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.3 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 3) (minute . 58)) (gustDirection . [7 0]) (gust . [10.1 0]))
 (\20220226131000 (prefNumber . 44) (observationNumber . 112) (temp . [12.8 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.6 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 7)) (gustDirection . [8 0]) (gust . [10.6 0]))
 (\20220226132000 (prefNumber . 44) (observationNumber . 112) (temp . [12.7 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [6.9 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 20)) (gustDirection . [8 0]) (gust . [10.9 0]))
 (\20220226133000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.0 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0]))
 (\20220226134000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.4 0]) (maxTempTime (hour . 3) (minute . 55)) (maxTemp . [13.3 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0]))
 (\20220226135000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [7.9 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 28)) (gustDirection . [8 0]) (gust . [12.5 0]))
 (\20220226140000 (prefNumber . 44) (observationNumber . 112) (temp . [12.9 0]) (snow1h . [0 :null]) (snow6h . [0 :null]) (snow12h . [0 :null]) (snow24h . [0 :null]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [8 0]) (wind . [9.3 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0]))
 (\20220226141000 (prefNumber . 44) (observationNumber . 112) (temp . [12.6 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.8 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0]))
 (\20220226142000 (prefNumber . 44) (observationNumber . 112) (temp . [13.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [8.0 0]) (maxTempTime (hour . 4) (minute . 41)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0]))
 (\20220226143000 (prefNumber . 44) (observationNumber . 112) (temp . [13.0 0]) (sun10m . [10 0]) (sun1h . [1.0 0]) (precipitation10m . [0.0 0]) (precipitation1h . [0.0 0]) (precipitation3h . [0.0 0]) (precipitation24h . [0.0 0]) (windDirection . [7 0]) (wind . [7.2 0]) (maxTempTime (hour . 5) (minute . 29)) (maxTemp . [13.4 0]) (minTempTime (hour . 20) (minute . 22)) (minTemp . [-2.7 0]) (gustTime (hour . 4) (minute . 58)) (gustDirection . [8 0]) (gust . [15.2 0])))

1度のアクセスで10分毎の計測データが3時間分まとめて取得できるので、必要なだけアクセスして結果をつなぎ合わせてから不要な部分をカットしています。サーバへのアクセス頻度が高くなりがちなのでご注意ください(とは言え気象庁の観測データ一覧ページで行っていることと同じではあります)。

過去数日程度のデータしか取得できないようです。それ以前のデータは気象庁|各種データ・資料のあたりから取得しましょう。