Zgragselus

AI - Python

Feb 9th, 2026
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.82 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. """
  3. Load a CSV file into a PostgreSQL table.
  4.  
  5. Usage example:
  6. python cpt/load_cpt_csv.py --file cpt/ProcedureSearchList_2026.csv --table procedure_search_list_2026 \
  7.  --host localhost --port 5432 --dbname mydb --user myuser --password secret
  8.  
  9. The script will create the target table with all columns as text (if it doesn't exist),
  10. sanitize header names into safe column identifiers, and then COPY the CSV into Postgres.
  11. """
  12. import argparse
  13. import csv
  14. import os
  15. import re
  16. import sys
  17. from typing import List
  18.  
  19. import psycopg2
  20.  
  21.  
  22. def sanitize_column(name: str) -> str:
  23.     name = name.strip()
  24.     name = name.lower()
  25.     # replace non-alphanumeric with underscore
  26.     name = re.sub(r"[^a-z0-9]+", "_", name)
  27.     name = name.strip("_")
  28.     if not name:
  29.         name = "col"
  30.     if re.match(r"^[0-9]", name):
  31.         name = "col_" + name
  32.     return name
  33.  
  34.  
  35. def unique_names(names: List[str]) -> List[str]:
  36.     out = []
  37.     seen = {}
  38.     for n in names:
  39.         base = n
  40.         i = 1
  41.         while n in seen:
  42.             n = f"{base}_{i}"
  43.             i += 1
  44.         seen[n] = True
  45.         out.append(n)
  46.     return out
  47.  
  48.  
  49. def create_table_if_needed(cur, table: str, columns: List[str]):
  50.     cols_sql = ", ".join(f'"{c}" text' for c in columns)
  51.     sql = f"CREATE TABLE IF NOT EXISTS \"{table}\" ({cols_sql});"
  52.     cur.execute(sql)
  53.  
  54.  
  55. def main():
  56.     p = argparse.ArgumentParser(description="Load CSV into Postgres table")
  57.     p.add_argument("--file", required=True, help="Path to CSV file")
  58.     p.add_argument("--table", required=True, help="Target table name")
  59.     p.add_argument("--host", default=os.environ.get("PGHOST", "localhost"))
  60.     p.add_argument("--port", default=os.environ.get("PGPORT", "5432"))
  61.     p.add_argument("--dbname", default=os.environ.get("PGDATABASE"))
  62.     p.add_argument("--user", default=os.environ.get("PGUSER"))
  63.     p.add_argument("--password", default=os.environ.get("PGPASSWORD"))
  64.     p.add_argument("--delimiter", default=None, help="CSV delimiter (auto-detect if omitted)")
  65.     args = p.parse_args()
  66.  
  67.     if not args.dbname or not args.user or not args.password:
  68.         print("Please provide --dbname, --user and --password (or set PGDATABASE/PGUSER/PGPASSWORD env vars)")
  69.         sys.exit(1)
  70.  
  71.     if not os.path.exists(args.file):
  72.         print(f"CSV file not found: {args.file}")
  73.         sys.exit(1)
  74.  
  75.     # Detect delimiter and header
  76.     with open(args.file, "r", newline="", encoding="utf-8") as fh:
  77.         sample = fh.read(8192)
  78.         sniffer = csv.Sniffer()
  79.         try:
  80.             dialect = sniffer.sniff(sample)
  81.             delimiter = dialect.delimiter
  82.         except Exception:
  83.             delimiter = args.delimiter or ","
  84.         fh.seek(0)
  85.         reader = csv.reader(fh, delimiter=delimiter)
  86.         try:
  87.             header = next(reader)
  88.         except StopIteration:
  89.             print("CSV file appears empty")
  90.             sys.exit(1)
  91.  
  92.     sanitized = [sanitize_column(h or f"col{i+1}") for i, h in enumerate(header)]
  93.     sanitized = unique_names(sanitized)
  94.  
  95.     # Connect to Postgres
  96.     conn_str = (
  97.         f"host={args.host} port={args.port} dbname={args.dbname} user={args.user} password={args.password}"
  98.     )
  99.     conn = psycopg2.connect(conn_str)
  100.     try:
  101.         cur = conn.cursor()
  102.         create_table_if_needed(cur, args.table, sanitized)
  103.         conn.commit()
  104.  
  105.         cols_list = ", ".join(f'"{c}"' for c in sanitized)
  106.         copy_sql = f"COPY \"{args.table}\" ({cols_list}) FROM STDIN WITH CSV HEADER DELIMITER '{delimiter}'"
  107.  
  108.         with open(args.file, "r", encoding="utf-8", newline="") as fh:
  109.             cur.copy_expert(copy_sql, fh)
  110.         conn.commit()
  111.         print(f"Loaded {args.file} into {args.table} ({len(sanitized)} columns)")
  112.     finally:
  113.         conn.close()
  114.  
  115.  
  116. if __name__ == "__main__":
  117.     main()
Advertisement
Add Comment
Please, Sign In to add comment