質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

988閲覧

大容量データを読み込むとpcがフリーズしてしまうため、解決案をご教示ください。

Dobutori

総合スコア2

XML

XMLは仕様の1つで、マークアップ言語群を構築するために使われています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2023/02/08 04:09

実現したいこと

 自動車のIDや座標、速度、角度などが含んだ午前6時から午前10時までのデータを1秒ごとにPythonプログラムで読み込み、ID、座標、速度だけをテキストファイルに抽出したいです。

前提

・自動車データの容量
1秒ごとに複数(平均4000台)の車両のID、座標、角度、速度、タイプなどの情報が24時間分データが記載されています。データはSumo simulationという自動車シミュレーションの解析ソフトから入手しました。形式はxmlで、サイズは66[GB]あります。

・自動車データの一部

<timestep time="0.00"/> <timestep time="1.00"> <vehicle id="12145" x="15738.31" y="12960.48" angle="222.08" type="passenger" speed="8.27" pos="0.00" edge="101186592#1" slope="0.00"/> <vehicle id="21033" x="11763.45" y="8734.78" angle="113.96" type="passenger" speed="4.62" pos="0.00" edge="-135860932#5" slope="0.00"/> <vehicle id="22846" x="12003.84" y="7245.94" angle="286.08" type="passenger" speed="8.73" pos="0.00" edge="329301856#1" slope="0.00"/> <vehicle id="5498" x="9390.46" y="14695.02" angle="275.69" type="passenger" speed="10.42" pos="0.00" edge="486666536" slope="0.00"/> <vehicle id="685" x="13927.17" y="17398.08" angle="185.71" type="passenger" speed="8.50" pos="0.00" edge="-134109962" slope="0.00"/> </timestep> <timestep time="2.00"> <vehicle id="10154" x="13166.76" y="13330.08" angle="297.20" type="passenger" speed="6.96" pos="0.00" edge="572714693#1" slope="0.00"/> <vehicle id="10357" x="13652.13" y="12984.96" angle="117.33" type="passenger" speed="9.04" pos="0.00" edge="36927091#2" slope="0.00"/> <vehicle id="12145" x="15738.31" y="12960.48" angle="222.08" type="passenger" speed="8.27" pos="0.00" edge="101186592#1" slope="0.00"/> <vehicle id="19469" x="12549.67" y="11159.53" angle="26.71" type="passenger" speed="4.42" pos="0.00" edge="-50175538#0" slope="0.00"/> <vehicle id="21033" x="11763.45" y="8734.78" angle="113.96" type="passenger" speed="4.62" pos="0.00" edge="-135860932#5" slope="0.00"/> <vehicle id="22846" x="12003.84" y="7245.94" angle="286.08" type="passenger" speed="8.73" pos="0.00" edge="329301856#1" slope="0.00"/> <vehicle id="5498" x="9390.46" y="14695.02" angle="275.69" type="passenger" speed="10.42" pos="0.00" edge="486666536" slope="0.00"/> <vehicle id="6205" x="13210.50" y="14248.27" angle="201.25" type="passenger" speed="5.81" pos="0.00" edge="-23182358#9" slope="0.00"/> <vehicle id="685" x="13927.17" y="17398.08" angle="185.71" type="passenger" speed="8.50" pos="0.00" edge="-134109962" slope="0.00"/> <vehicle id="7228" x="14452.42" y="13726.45" angle="209.55" type="passenger" speed="4.71" pos="0.00" edge="196497372#0" slope="0.00"/> </timestep>   ・・・

使用するプログラムのソースコード

xmlの一行一行読み込み、データを抽出するプログラム

Python

1# 24時間の車両データを6~10時までのデータに抽出 2 3import sys 4from xml.etree.ElementTree import iterparse 5import r 6 7output_file = "Tust_0610.txt" # 出力ファイル 8FCDOutput = 'Tust24.xml' # 入力ファイル 9 10time_s=21600 # 開始時間 11time_e=36000 # 終了時間 12 13# xmlデータを読み込み、ID.座標、速度を抽出する関数 14def SUMOTraceParser(FCDOutput): 15 data_list=[] 16 # ファイルopen 17 f = open(output_file, "w") 18 # xmlファイルのstart,endドックを取得 19 doc = iterparse(FCDOutput, events=('start', 'end')) 20 # Skip the root element 21 event, root = next(doc) 22 23 # 読み込み 24 for event, elem in doc: 25 if event == 'start': 26 if elem.tag == 'timestep': #時間を抽出 27 # 時間tを読み込み 28 t = float(elem.attrib['time']) 29 elif elem.tag == 'vehicle' : # 車両の情報を抽出 30 # データの各要素位 31 id = int(str(elem.attrib['id'])) 32 x = int(float(elem.attrib['x'])) 33 y = int(float(elem.attrib['y'])) 34 speed=float(elem.attrib['speed']) 35 # x,yは整数型で出力(データ容量削減のため) 36 data_list.append((id,x,y,speed)) 37 elif event == 'end': 38 if elem.tag == 'timestep'and t>time_s: 39 print("t=%d\n"%(int(t))) 40 for i in range(len(data_list)): 41 f.write("%d,%d,%d,%.2f\n"%(data_list[i][0],data_list[i][1],data_list[i][2],data_list[i][3])) 42 print("%d,%d,%d,%.2f\n"%(data_list[i][0],data_list[i][1],data_list[i][2],data_list[i][3])) 43 f.write("<end>\n") 44 data_list=[] 45 if t == time_e+1: 46 f.close() 47 sys.exit() 48 49# main 50if __name__ == '__main__': 51 SUMOTraceParser(FCDOutput)

###問題点
プログラムを読み込むと途中でフリーズしてしまう。

試したこと

Sumosimulationのコマンドでデータを1時間で分割することで動くようになったが、データが少し変わってしまうため、できれば6時〜10時の1つデータでプログラムを動かしたい。

PCのスペック

メモリ:15.6[GiB]
プロセッサー:Intel® Core™ i7-4770 CPU @ 3.40GHz × 8
グラフィック:NVIDIA Corporation GK208 [GeForce GT 640 Rev. 2]
容量 2TB (HDD)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2023/02/08 04:19

複数の PC を使い、分散処理をする。
jbpb0

2023/02/08 05:04

https://qiita.com/shuntaroy/items/32e20e9bdab92aff0a89 の「iter するとき(メモリを食べない)」の、 「都度中身を.clear()すればエレメントの情報がメモリから退散します。」 みたいなことはできないのでしょうか? コードの内容をちゃんと理解してないので、外してたらごめんなさい
otn

2023/02/08 05:08

timestep毎にデータを保存してまとめて書いているようですが、処理内容的にまとめる意味がありません。 実際には、vehicleを読む毎に都度書くのでは駄目な集計のような処理が入っているのでしょうか?
Bego

2023/02/08 05:32

フリーズするのは、プログラム or PC のどっちですか? いずれにしても、どこで止まっているのかをきちんと究明しない限り、根本的な対策は難しいと思います。 止まってる箇所を特定するには、デバッガをアタッチさせてライブデバッグするか、ダンプ ファイルを採取しそれを解析するかの、いずれかの調査が必要になると思います。 プログラムがフリーズするのであれば、問題現象が発生したタイミングでタスクマネージャーからダンプを生成させ、それをデバッガで読み込み各スレッドの状態を確認すれば、どこで止まっているか特定できると思います。
n24bass

2023/02/08 06:31 編集

XML としてではなく、単にテキストとして1行ずつ読んでの処理ではダメでしょうか。改行が含まれていないなら < から /> まででも1レコードとして読んで正規表現マッチングなりで値を取得とか。
guest

回答2

0

rootを解放することで動かすことができました!メモリの解放についても学べたのでとても良かったです。ありがとうございます!

投稿2023/02/08 07:37

Dobutori

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

実際に試していませんので参考程度の回答ですがPython running out of memory parsing XML using cElementTree.iterparseの回答にあるようにジェネレータにしてend時にclearするとメモリ節約できるようです。

追記

大量データでは試していませんが、問題なく処理できているようです。
なお、提示コードにおいて、XMLに開始時間よりも前の時間のデータが含まれている場合、最初の時間のデータにそれらが含まれるような動作になっているようです。
ちょっと違和感ありますが、以下テストコードでもそのままの動作にしています。

Python

1from xml.etree.ElementTree import iterparse 2from io import StringIO 3 4# テストデータ 5s = """<dummy> 6 <timestep time="1"> 7 <vehicle id="1"/> 8 </timestep> 9 <timestep time="2"> 10 <vehicle id="2"/> 11 <vehicle id="3"/> 12 </timestep> 13 <timestep time="3"> 14 <vehicle id="4"/> 15 <vehicle id="5"/> 16 <vehicle id="6"/> 17 </timestep> 18 <timestep time="4"> 19 <vehicle id="9"/> 20 </timestep> 21</dummy>""" 22 23 24time_s=1 # これよりも大きい時間 25time_e=3 # 終了時間 26 27def get_element(xml): 28 data_list=[] 29 doc = iterparse(xml, events=('start', 'end')) 30 event, root = next(doc) 31 32 for event, elem in doc: 33 if event == 'start': 34 if elem.tag == 'timestep': #時間を抽出 35 # 時間tを読み込み 36 t = float(elem.attrib['time']) 37 elif elem.tag == 'vehicle' : # 車両の情報を抽出 38 id = int(str(elem.attrib['id'])) 39 data_list.append((id,)) # 時間に関係なく蓄積しているけどまあいいか 40 elif event == 'end': 41 if elem.tag == 'timestep'and t > time_s: 42 yield t, data_list 43 data_list=[] 44 root.clear() 45 46 if t == time_e+1: # 完全一致だけどまあいいか 47 break 48 49# ファイル出力などの処理は呼出元でおこなう 50elems = get_element(StringIO(s)) 51for e in elems: 52 print(e) 53""" 54(2.0, [(1,), (2,), (3,)]) 55(3.0, [(4,), (5,), (6,)]) 56"""

あるいは、そもそもジェネレータにせずとも、たんにend時にclearするだけでもよいかもしれません。

投稿2023/02/08 04:27

編集2023/02/08 05:14
can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問