Skip to content

Commit 9df85e7

Browse files
python utility to import gtfs transport stations
1 parent a5f67f9 commit 9df85e7

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/usr/bin/env python3
2+
import csv
3+
import psycopg2
4+
from psycopg2.extras import execute_values
5+
from typing import Optional
6+
import argparse
7+
8+
'''
9+
Usage:
10+
python3 tools/import_stations.py \
11+
--csv stops.csv \
12+
--city Flensburg \
13+
--country DEU \
14+
--host localhost \
15+
--port 5432 \
16+
--db uranus \
17+
--user postgres \
18+
--password mysecretpassword
19+
20+
python3 tools/import_transport_station_gtfs_stops.py --csv /Volumes/RoaldMedia1/OpenData/Transport/GTFS/SH/stops.txt --city Flensburg --country DEU --host localhost --port 5432 --db oklab --user roaldchristesen --password ''
21+
'''
22+
23+
# --- your import function ---
24+
def import_transport_stations(
25+
csv_file_path: str,
26+
city: Optional[str] = None,
27+
country: Optional[str] = None,
28+
db_config: dict = None
29+
):
30+
if db_config is None:
31+
db_config = {
32+
"host": "localhost",
33+
"database": "uranus",
34+
"user": "postgres",
35+
"password": "",
36+
}
37+
38+
conn = psycopg2.connect(**db_config)
39+
cur = conn.cursor()
40+
41+
insert_sql = """
42+
INSERT INTO uranus.transport_station (
43+
name, geo_pos, gtfs_station_code, gtfs_location_type,
44+
city, country, gtfs_parent_station, gtfs_wheelchair_boarding, gtfs_zone_id
45+
) VALUES %s
46+
ON CONFLICT (gtfs_station_code) DO UPDATE
47+
SET
48+
name = EXCLUDED.name,
49+
geo_pos = EXCLUDED.geo_pos,
50+
gtfs_location_type = EXCLUDED.gtfs_location_type,
51+
city = EXCLUDED.city,
52+
country = EXCLUDED.country,
53+
gtfs_parent_station = EXCLUDED.gtfs_parent_station,
54+
gtfs_wheelchair_boarding = EXCLUDED.gtfs_wheelchair_boarding,
55+
gtfs_zone_id = EXCLUDED.gtfs_zone_id
56+
"""
57+
58+
values = []
59+
60+
with open(csv_file_path, newline="", encoding="utf-8") as csvfile:
61+
reader = csv.DictReader(csvfile)
62+
for row in reader:
63+
stop_name = row.get("stop_name", "").strip()
64+
stop_code = row.get("stop_id", "").strip() or None
65+
lat = row.get("stop_lat")
66+
lon = row.get("stop_lon")
67+
location_type = int(row.get("location_type", 0))
68+
parent_station = row.get("parent_station") or None
69+
wheelchair_boarding = int(row.get("wheelchair_boarding", 0))
70+
zone_id = row.get("zone_id") or None
71+
72+
try:
73+
lat_f = float(lat)
74+
lon_f = float(lon)
75+
except (TypeError, ValueError):
76+
print(f"Skipping invalid row: {row}")
77+
continue
78+
79+
point_wkt = f"SRID=4326;POINT({lon_f} {lat_f})"
80+
81+
values.append((
82+
stop_name,
83+
point_wkt,
84+
stop_code,
85+
location_type,
86+
city,
87+
country,
88+
parent_station,
89+
wheelchair_boarding,
90+
zone_id
91+
))
92+
93+
if not values:
94+
print("No valid rows to insert.")
95+
cur.close()
96+
conn.close()
97+
return
98+
99+
execute_values(
100+
cur,
101+
insert_sql,
102+
values,
103+
template="""(
104+
%s,
105+
ST_GeomFromText(%s),
106+
%s,
107+
%s,
108+
%s,
109+
%s,
110+
%s,
111+
%s,
112+
%s
113+
)"""
114+
)
115+
116+
conn.commit()
117+
cur.close()
118+
conn.close()
119+
print(f"Imported {len(values)} transport stations successfully.")
120+
121+
122+
# --- CLI entry point ---
123+
if __name__ == "__main__":
124+
parser = argparse.ArgumentParser(description="Import GTFS stops into transport_station table")
125+
parser.add_argument("--csv", required=True, help="Path to the CSV file")
126+
parser.add_argument("--city", default=None, help="City name to assign")
127+
parser.add_argument("--country", default=None, help="Country code to assign")
128+
parser.add_argument("--host", default="localhost", help="PostgreSQL host")
129+
parser.add_argument("--port", default=5432, type=int, help="PostgreSQL port")
130+
parser.add_argument("--db", required=True, help="Database name")
131+
parser.add_argument("--user", required=True, help="Database user")
132+
parser.add_argument("--password", required=True, help="Database password")
133+
134+
args = parser.parse_args()
135+
136+
db_config = {
137+
"host": args.host,
138+
"port": args.port,
139+
"database": args.db,
140+
"user": args.user,
141+
"password": args.password,
142+
}
143+
144+
import_transport_stations(args.csv, args.city, args.country, db_config)

0 commit comments

Comments
 (0)