Pre-release
This release is a pre-release and may not be stable for production use.
pg-export-import
Stream-export filtered PostgreSQL rows to CSV and bulk-import via COPY. Supports multi-table, FK-aware pipelines with idempotent re-runs.
Installation
pip install pg-export-import
Requirements
- Python 3.11+
- PostgreSQL (source and target can be on different servers)
Library usage
Single table
from pg_export_import import ConnectionConfig, export_and_import
src = ConnectionConfig(host="db1.example.com", dbname="prod", user="app", password="...")
tgt = ConnectionConfig(host="db2.example.com", dbname="staging", user="app", password="...")
result = export_and_import(
source_config=src,
target_config=tgt,
source_table="public.orders",
target_table="public.orders",
where_clause="created_at >= %s",
where_params=("2024-01-01",),
csv_path="/data/exports/orders.csv", # optional; auto-generated if omitted
delete_before_import=True, # optional; delete target rows before importing (default False)
# delete_where_clause="created_at >= %s", # optional; defaults to where_clause
# delete_where_params=("2024-01-01",), # optional; defaults to where_params
)
print(result.status, result.exported_count, result.imported_count, result.deleted_count)
result.status is one of "success", "export_failed", "delete_failed", or "import_failed".
Multi-table pipeline
from pg_export_import import ConnectionConfig, run_pipeline
src = ConnectionConfig(...)
tgt = ConnectionConfig(...)
tables = [
# parents before children (FK order)
{"source_table": "customers", "target_table": "customers", "where_clause": ""},
{"source_table": "orders", "target_table": "orders", "where_clause": "created_at >= %s", "where_params": ("2024-01-01",)},
{"source_table": "order_items", "target_table": "order_items", "where_clause": "created_at >= %s", "where_params": ("2024-01-01",)},
]
results = run_pipeline(
source_config=src,
target_config=tgt,
tables=tables,
csv_dir="/data/exports", # optional; defaults to tempdir
fetch_size=5000, # optional; rows per round-trip (default 5000)
delete_before_import=True, # optional; set False to append without deleting (default True)
)
for r in results:
print(r["table"], r["status"], r["exported"], r["imported"])
CSV file naming
Each pipeline run captures a single timestamp once at start. All tables in that run share the same timestamp:
{csv_dir}/{source_table}_{YYYYMMDD_HHMMSS}.csv
Dots in schema-qualified names become underscores:
| source_table | csv_dir | filename |
|---|---|---|
orders |
/data/exports |
orders_20250320_143022.csv |
public.orders |
/data/exports |
public_orders_20250320_143022.csv |
- The
csv_diris created automatically if it does not exist. - On success, CSV files are deleted.
- On failure, CSV files are preserved for debugging or re-import.
Table config schema
Each entry in the tables argument to run_pipeline supports:
| Key | Type | Required | Description |
|---|---|---|---|
source_table |
str | yes | Source table reference ("table" or "schema.table") |
target_table |
str | yes | Target table reference |
where_clause |
str | yes | SQL WHERE fragment (empty string = all rows) |
where_params |
tuple | dict | None | no | Bind values for where_clause placeholders |
delete_where_clause |
str | no | WHERE fragment for DELETE on target (defaults to where_clause) |
delete_where_params |
tuple | dict | None | no | Bind values for delete_where_clause |
fetch_size |
int | no | Per-table override for rows fetched per round-trip; takes precedence over run_pipeline's fetch_size argument |
delete_before_import |
bool | no | Per-table override; when False, skips DELETE for this table regardless of the pipeline-level argument |
Security notes
where_clauseis embedded as a raw SQL fragment — it must come from trusted application code, never from user input.- Runtime filter values must be passed via
where_params, not interpolated into the clause string. - All table and column identifiers are validated and safely quoted via
psycopg.sql.Identifier.
Release files for pg-export-import 0.1.0b3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pg_export_import-0.1.0b3.tar.gz | 17.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pg_export_import-0.1.0b3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.1 kB
Release files / pg_export_import-0.1.0b3.tar.gz
| Download URL | pg_export_import-0.1.0b3.tar.gz |
|---|---|
| Size | 17.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
475f48b67fbe66fbfd65f4e91fdffd7fe6be2bae2910d6df68d14dc2f315b344
|
|
BLAKE2b-256 checksum How to use checksums |
a23342407cf25d5d0afaae98e39caf7e6104f77bac165ce7d5f4674389a0c599
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pg_export_import-0.1.0b3-py3-none-any.whl
| Download URL | pg_export_import-0.1.0b3-py3-none-any.whl |
|---|---|
| Size | 17.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7d689d1a254c5942b34dcff49ab49c7e2265382a4ffdb481cd0137e66f9f2df4
|
|
BLAKE2b-256 checksum How to use checksums |
1489680b8592fcd1c01e9aaf798e6793570d09a3196599bb71d33e7921c29832
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|