99 python commons/import_paths.py
1010"""
1111
12- import argparse
1312import json
1413import os
1514import sys
16- from concurrent .futures import ThreadPoolExecutor , as_completed
1715from pathlib import Path
1816
1917from tqdm import tqdm
@@ -48,58 +46,52 @@ def import_path_data(
4846 FileNotFoundError: ファイルが存在しない
4947 ValueError: JSONフォーマットが不正
5048 """
49+ # ファイル存在チェック
5150 if not os .path .exists (json_path ):
5251 raise FileNotFoundError (f"File not found: { json_path } " )
5352
54- # JSONデータを読み込み
53+ # JSONファイルを読み込み
5554 with open (json_path , "r" , encoding = "utf-8" ) as f :
5655 data = json .load (f )
5756
58- # データ形式を判定
57+ # データ形式を判定(Overpass API形式または配列形式)
5958 if isinstance (data , dict ) and "elements" in data :
60- # OpenStreetMap Overpass API形式: {"elements": [...]}
6159 paths_data = data ["elements" ]
6260 elif isinstance (data , list ):
63- # 配列
6461 paths_data = data
6562 else :
6663 raise ValueError (
6764 "Invalid JSON format: expected object with 'elements' key or array"
6865 )
6966
70- # wayタイプのみフィルタ
71- # paths_data = [p for p in paths_data if p.get("type") == "way"]
72- # print(f" Total ways: {len(paths_data)}")
73-
74- # 統計情報
67+ # 統計情報の初期化
7568 stats = {
7669 "total" : len (paths_data ),
7770 "created" : 0 ,
7871 "skipped" : 0 ,
7972 "errors" : 0 ,
8073 }
8174
82- # 各パスデータをインポート
83- # print("\nImporting paths...")
84- # print(f"Batch size: {batch_size} (commits every {batch_size} items)")
85-
75+ # 各パスデータを処理
8676 with tqdm (
8777 paths_data , desc = f"Processing paths in { Path (json_path ).name } " , unit = "path"
8878 ) as pbar :
8979 for i , path_data in enumerate (pbar , 1 ):
9080 try :
81+ # 基本情報を取得
9182 osm_id = path_data .get ("id" )
9283 path_type = path_data .get ("type" ) or "way"
9384 geometry = path_data .get ("geometry" , [])
9485
95- # 既存チェック
86+ # 既存データのチェック
9687 if PathModel .objects .filter (osm_id = osm_id ).exists ():
9788 if skip_existing :
9889 stats ["skipped" ] += 1
9990 continue
10091
92+ # データベースへの保存(トランザクション内)
10193 with transaction .atomic ():
102- # Pathオブジェクトを作成
94+ # Pathレコードを作成
10395 bounds = path_data .get ("bounds" , {})
10496 path = PathModel .objects .create (
10597 osm_id = osm_id ,
@@ -110,7 +102,7 @@ def import_path_data(
110102 maxlon = bounds .get ("maxlon" ),
111103 )
112104
113- # Geometriesを追加
105+ # ジオメトリ情報を保存
114106 nodes = path_data .get ("nodes" , [])
115107 for idx , geom in enumerate (geometry ):
116108 PathGeometry .objects .create (
@@ -121,7 +113,7 @@ def import_path_data(
121113 sequence = idx ,
122114 )
123115
124- # Tagsを追加
116+ # タグ情報を保存
125117 tags = path_data .get ("tags" , {})
126118 if tags :
127119 PathTag .objects .create (
@@ -132,31 +124,39 @@ def import_path_data(
132124 kuma = tags .get ("kuma" ),
133125 )
134126
127+ # 地理情報フィールドを更新
128+ path .update_geo_fields ()
129+ path .save (
130+ update_fields = [
131+ "route" ,
132+ "bbox" ,
133+ "minlon" ,
134+ "minlat" ,
135+ "maxlon" ,
136+ "maxlat" ,
137+ ]
138+ )
139+
135140 stats ["created" ] += 1
136141 except Exception as e :
137142 stats ["errors" ] += 1
138- pbar .write (f" Error: OSM ID { path_data .get ('id' , 'Unknown' )} - { str (e )} " )
143+ pbar .write (f"❌ Error importing OSM ID { path_data .get ('id' , 'Unknown' )} : { str (e )} " )
139144
140145 return stats
141146
142147
143148def main ():
144149 """メイン関数"""
145- parser = argparse .ArgumentParser (description = "登山道データJSONインポートスクリプト" )
146- parser .add_argument (
147- "--workers" ,
148- type = int ,
149- default = 1 ,
150- help = "並列処理のワーカースレッド数 (デフォルト: 1)" ,
151- )
152- args = parser .parse_args ()
153150
151+ # データフォルダのパスを設定
154152 data_folder = Path (__file__ ).parent .parent / "datas" / "paths_merged"
155153
154+ # フォルダ存在チェック
156155 if not data_folder .exists ():
157156 print (f"❌ Error: Data folder not found: { data_folder } " )
158157 sys .exit (1 )
159158
159+ # JSONファイルを検索
160160 files = list (data_folder .glob ("*.json" ))
161161
162162 if not files :
@@ -166,11 +166,13 @@ def main():
166166 batch_size = 1000
167167
168168 try :
169+ # インポート開始
169170 print ("=" * 60 )
170- print ("Path Data Import" )
171+ print ("🚀 Path Data Import Started" )
172+ print (f"📁 Found { len (files )} JSON file(s) in { data_folder .name } " )
171173 print ("=" * 60 )
172- print (f"Found { len (files )} JSON file(s)" )
173174
175+ # 統計情報の初期化
174176 total_stats = {
175177 "total" : 0 ,
176178 "created" : 0 ,
@@ -181,56 +183,39 @@ def main():
181183 with tqdm (
182184 total = len (files ), desc = "Processing JSON files" , unit = "file"
183185 ) as overall_pbar :
184- with ThreadPoolExecutor (max_workers = args .workers ) as executor :
185- future_to_file = {
186- executor .submit (
187- import_path_data , str (json_path ), True , batch_size
188- ): json_path
189- for json_path in files
190- }
191-
192- for future in as_completed (future_to_file ):
193- json_path = future_to_file [future ]
194- try :
195- result = future .result ()
196- # print("\n" + "-" * 60)
197- # print("📊 File Import Summary")
198- # print("-" * 60)
199- # print(f" File: {json_path.name}")
200- # print(f" Total: {result['total']}")
201- # print(f" ✅ Created: {result['created']}")
202- # print(f" ⏭️ Skipped: {result['skipped']}")
203- # print(f" ❌ Errors: {result['errors']}")
204- # print("-" * 60)
205-
206- # 累計を更新
207- total_stats ["total" ] += result ["total" ]
208- total_stats ["created" ] += result ["created" ]
209- total_stats ["skipped" ] += result ["skipped" ]
210- total_stats ["errors" ] += result ["errors" ]
211-
212- if result ["errors" ] > 0 :
213- print (
214- f"\n ⚠️ Warning: { result ['errors' ]} errors occurred during import"
215- )
216- except Exception as e :
217- print (f"\n ❌ Error processing file { json_path .name } : { e } " )
218- finally :
219- overall_pbar .update (1 )
220-
221- # 最終サマリー
186+ for json_path in files :
187+ try :
188+ result = import_path_data (str (json_path ), True , batch_size )
189+
190+ # 統計を累積
191+ total_stats ["total" ] += result ["total" ]
192+ total_stats ["created" ] += result ["created" ]
193+ total_stats ["skipped" ] += result ["skipped" ]
194+ total_stats ["errors" ] += result ["errors" ]
195+
196+ # エラーがあれば警告表示
197+ if result ["errors" ] > 0 :
198+ print (
199+ f"\n ⚠️ Warning: { result ['errors' ]} error(s) in { json_path .name } "
200+ )
201+ except Exception as e :
202+ print (f"\n ❌ Fatal error processing { json_path .name } : { e } " )
203+ finally :
204+ overall_pbar .update (1 )
205+
206+ # 最終結果の表示
222207 print ("\n " + "=" * 60 )
223- print ("📊 Total Import Summary " )
224- print ("=" * 60 )
225- print (f" Files: { len (files )} " )
226- print (f" Total: { total_stats ['total' ]} " )
227- print (f" ✅ Created: { total_stats ['created' ]} " )
228- print (f" ⏭️ Skipped: { total_stats ['skipped' ]} " )
229- print (f" ❌ Errors: { total_stats ['errors' ]} " )
208+ print ("✅ Import Completed Successfully " )
209+ print (f"📊 Summary:" )
210+ print (f" Files processed : { len (files )} " )
211+ print (f" Total paths : { total_stats ['total' ]} " )
212+ print (f" ✅ Created: { total_stats ['created' ]} " )
213+ print (f" ⏭️ Skipped: { total_stats ['skipped' ]} " )
214+ print (f" ❌ Errors: { total_stats ['errors' ]} " )
230215 print ("=" * 60 )
231216
232217 except Exception as e :
233- print (f"\n ❌ Error occurred: { e } " )
218+ print (f"\n ❌ Fatal error occurred: { e } " )
234219 import traceback
235220
236221 traceback .print_exc ()
0 commit comments