OpenStreetmap のタイルサーバーの運用ですが、またエラーで更新が止まってしまいました。トホホ。
しかし、今回は、こちらの記事で設定したメール通知のおかげですぐに気づくことができたのが不幸中の幸いでしょうかね? ですが、実際に対応が完了するまでにおおよそ一か月以上かかってしまいました。せっかく通知が来たのに時間がかかるとは難しいもんですね。
一応、原因調査や対策時のメモを残しておきます。
症状
出力されていたエラーは次のようなものです。
[2018-10-29 22:06:01] 4620 start import from seq-nr 53056, replag is 27 day(s) and 14 hour(s) [2018-10-29 22:06:01] 4620 downloading diff [2018-10-29 22:17:43] 4620 filtering diff Traceback (most recent call last): File "/home/osm/src/regional/trim_osc.py", line 131, in <module> for nd in root.xpath('//way[@id={}]/nd'.format(row[0])): File "src/lxml/lxml.etree.pyx", line 1587, in lxml.etree._Element.xpath (src/lxml/lxml.etree.c:61854) File "src/lxml/xpath.pxi", line 307, in lxml.etree.XPathElementEvaluator.__call__ (src/lxml/lxml.etree.c:178516) File "src/lxml/xpath.pxi", line 227, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:177421) lxml.etree.XPathEvalError: Invalid expression [2018-10-29 22:20:04] 4620 [error] Trim_osc error [2018-10-29 22:20:04] 4620 resetting state osm@map:/var/log/tiles$
詳細は置いといて、 trim_osc.py 内部の処理でこけているようです。
オープンソースなんでこちらを調べるのも一つの手なのですが、Githubのリポジトリを見ると、既にいくつかコミットがあります。なので、とりあえず最新版を pull して動作するか試してみます。
更新
ということで、更新します。
osm@map:~/src/regional$ git fetch osm@map:~/src/regional$ git merge origin/master
試します。
[2018-10-09 09:06:02] 653 start import from seq-nr 53056, replag is 7 day(s) and 1 hour(s) [2018-10-09 09:06:02] 653 downloading diff [2018-10-09 09:07:13] 653 filtering diff Traceback (most recent call last): File "/home/osm/src/regional/trim_osc.py", line 9, in <module> import psycopg2 ImportError: No module named 'psycopg2' [2018-10-09 09:07:14] 653 [error] Trim_osc error [2018-10-09 09:07:14] 653 resetting state
あれ?今度は別のエラーで落ちてます。
リポジトリを見ると
Force python3 · Zverik/regional@2271549 · GitHub
このコミットで python3 を使うようになったみたいです。 なるほど、多分、 psycopg2 の python3 用モジュールが無いんでしょうね。
ということで、python3 用モジュールをインストールしてやって再度試します。 ただし、 python3 のほうは pip 経由でモジュールをインストールしてみます(pipのほうがaptよりも新しいバージョンがインストールされるっぽいので)
mor@map:~$ sudo apt-get update mor@map:~$ sudo apt-get install pip3 mor@map:~$ su - osm osm@map:~$ pip3 install shapely osm@map:~$ pip3 install psycopg2 osm@map:~$ pip3 install lxml
pip でのインストールの場合、ユーザーごとにインストールされるようなので、実際にデータの更新をしているユーザー(osm)に切り替えてインストールします。 なお、インストールしたモジュールは、最初に設定した時のものと同じです。
で、再度試してみると。。。あれ?同じくエラーがでますね。
trim_osc.py の調査と修正
さて、最新版にしただけだと、エラーが解決できなかったので、頑張って処理を追いかけてみました。
上述したように、最新のリポジトリ(この時点では、)にアップして、動かしたころ、
osm@map:~/tmp/osmosis_test3$ ~/src/regional/trim_osc.py -d gis -p region.poly -z -v changes.osc.gz trimed.osc.gz /home/osm/.local/lib/python3.5/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>. """) Traceback (most recent call last): File "shapely/speedups/_speedups.pyx", line 234, in shapely.speedups._speedups.geos_linearring_from_py AttributeError: 'list' object has no attribute '__array_interface__' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/osm/src/regional/trim_osc.py", line 82, in <module> tpoly = poly_parse(options.poly) File "/home/osm/src/regional/trim_osc.py", line 42, in poly_parse result = Polygon(poly) File "/home/osm/.local/lib/python3.5/site-packages/shapely/geometry/polygon.py", line 240, in __init__ ret = geos_polygon_from_py(shell, holes) File "/home/osm/.local/lib/python3.5/site-packages/shapely/geometry/polygon.py", line 494, in geos_polygon_from_py ret = geos_linearring_from_py(shell) File "shapely/speedups/_speedups.pyx", line 319, in shapely.speedups._speedups.geos_linearring_from_py TypeError: object of type 'map' has no len() osm@map:~/tmp/osmosis_test3$
のようなエラーになりました。
エラーが shapely の部分で起きていたので、ライブラリを apt でインストールしたものに切り替えても試したのですが、結論としては、微妙に呼んでるライブラリなどが違うけど、大筋同じエラーになっていました。
元に戻って、スタックトレースをよく見ていくと、trim_osc.py の引数で与えている領域指定のファイル(polyのファイル)の処理で落ちているようです。
とりあえずbounding box を使い、poly を迂回して実行できるか試します。
osm@map:~/tmp/osmosis_test3$ ~/src/regional/trim_osc.py -d gis -b 136.202763 34.482312 136.6553727 34.4756217 -z -v changes.osc.gz trimed.osc.gz /home/osm/.local/lib/python3.5/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary ple ase use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>. """) Traceback (most recent call last): File "/home/osm/src/regional/trim_osc.py", line 161, in <module> for nd in root.xpath('//way[@id={}]/nd'.format(row[0])): File "src/lxml/etree.pyx", line 1577, in lxml.etree._Element.xpath File "src/lxml/xpath.pxi", line 307, in lxml.etree.XPathElementEvaluator.__call__ File "src/lxml/xpath.pxi", line 227, in lxml.etree._XPathEvaluatorBase._handle_result lxml.etree.XPathEvalError: Error in xpath expression
やはり落ちます。しかも、今回の作業のきっかけとなった最初のエラーと似たような箇所(xpath の処理)で落ちています。
ここまでの経緯を整理すると、最新版の trim_osc.py は2つの問題がありそうに思えます。
- poly でポリゴンがつくれない
- xpath でエラーになる
後者の xpath の問題は、今回のきっかけでも出てきましたね(まったく同じではないかもしれませんが)。
いろいろと調べると、どうも、昔、MLで指摘されていたようで、大きなファイルの場合 xpath に述語(predicate、四角いかっこでの指定)を与えて実行してもエラーとなる場合があったようです。
[lxml] lxml.etree.XPathEvalError: Invalid expression for correct XPath expression on large XML file
残念ながら、上記の ML では、問題の指摘以後、特に動きはなかったようです。
xpath 現象の確認
後者の問題を確かめるため、今回問題となった xml ファイルをダウンロードして、python3 のコンソールで同様にxpathを呼び出してエラーになるのを確認します。
その後、テキストエディタを使い、先頭の60行程度で別ファイルとして保存し、同じくコンソールで動かしてみると、同じようにxpathを指定しても正しく動きます。
ということで、ここはファイルサイズが大きい場合の xpath の述語の処理が怪しいと検討をつけ、 xpath の処理を述語を使わない形に修正しました(修正内容を Pull Request しておいたので、詳しくはそちらを参照)。 これで、動かすと、なんと、最後まで処理が進みました!
これで一個解決です。
ポリゴンファイルの確認
こちらの処理は
Polygon(poly)
という部分で落ちています。よくよく見てみると、python3 では mapの戻り値は map オブジェクトであり、listではないとのことです。 でも、Polygonのコンストラクタはtupleのリストが与えられることを想定しています。
きっとこれが原因ですね。
というわけで、poly を作るところで、
51c51 < poly.append(map(lambda x: float(x.strip()), l.split()[:2])) --- > poly.append(list(map(lambda x: float(x.strip()), l.split()[:2])))
のように、map を list に変換して情報を格納するようにしたら、問題なく動作するようになりました。
めでたしめでたし。
余談
一応、上記の修正内容は Pull Request で送ってるのですが、今日時点(2018/12/4)でまだ取り込んでもらえていません。 まあ、進捗は GitHub上のリポジトリ を見ればわかるので、そちらを追いかけてください。