Sling
Sling is a modern ELT (Extract, Load, Transform) data movement tool that allows users to rapidly move data between various databases, data warehouses, and cloud services using a simple Python API or CLI. It supports a wide range of connectors and focuses on ease of use and high performance. The current version is 1.5.15, with a rapid release cadence (multiple updates per month).
Common errors
-
sling.exceptions.SlingConnectionException: Failed to connect to database: fe_sendauth: no password supplied
cause Incorrect or missing authentication credentials (user, password) for the database connection.fixVerify that the `user` and `password` parameters in your `Connection` object are correct and match the database server's requirements. Ensure environment variables (if used) are properly set and accessible. -
ModuleNotFoundError: No module named 'sling.connections'
cause Attempting to import submodules directly instead of the top-level package. All core classes and functions are exposed directly under the `sling` package.fixChange your import statement from `from sling.connections import Connection` (or similar for other components) to `from sling import Connection` (or `from sling import Source, Target, run`). -
KeyError: 'SomeEnvVar'
cause Attempting to access an environment variable directly via `os.environ['KEY']` which is not set, instead of using `os.environ.get('KEY', default_value)`.fixUse `os.environ.get('KEY', '')` or `os.environ.get('KEY', None)` to safely retrieve environment variables and provide a default value or handle the `None` case, preventing the `KeyError`.
Warnings
- gotcha Connection parameters vary significantly by connection type. Ensure you consult the documentation for the specific source/target connector (e.g., PostgreSQL, Snowflake, S3) to provide all required and optional parameters.
- gotcha Sling provides both a Python library for programmatic use and a CLI tool. While `sling run` works for both, the CLI allows managing connections and sources via configuration files, which is separate from Python API's direct object instantiation.
- gotcha Schema inference might not always perfectly match complex data types or custom schemas. Sometimes, manual schema mapping or data type casting is required.
Install
-
pip install sling -
pip install sling[snowflake,postgres]
Imports
- Connection
from sling.connections import Connection
from sling import Connection
- Source
from sling import Source
- Target
from sling import Target
- run
from sling.jobs import run
from sling import run
Quickstart
import os
from sling import Connection, Source, Target, run
# Configure connections using environment variables for sensitive data
# For a real run, ensure these environment variables are set:
# SLING_PG_HOST, SLING_PG_USER, SLING_PG_PASS, SLING_PG_DB
# SLING_SNF_ACCOUNT, SLING_SNF_USER, SLING_SNF_PASS, SLING_SNF_DB, SLING_SNF_WAREHOUSE
postgres_conn = Connection(
name='my_postgres',
type='postgres',
host=os.environ.get('SLING_PG_HOST', 'localhost'),
port=5432,
user=os.environ.get('SLING_PG_USER', 'user'),
password=os.environ.get('SLING_PG_PASS', 'password'),
database=os.environ.get('SLING_PG_DB', 'source_db')
)
snowflake_conn = Connection(
name='my_snowflake',
type='snowflake',
account=os.environ.get('SLING_SNF_ACCOUNT', 'your_account'),
user=os.environ.get('SLING_SNF_USER', 'user'),
password=os.environ.get('SLING_SNF_PASS', 'password'),
database=os.environ.get('SLING_SNF_DB', 'target_db'),
warehouse=os.environ.get('SLING_SNF_WAREHOUSE', 'COMPUTE_WH')
)
# Define source and target for a simple table copy
source_table = Source(
connection=postgres_conn,
object='public.my_source_table'
)
target_table = Target(
connection=snowflake_conn,
object='public.my_target_table',
mode='full_refresh' # or 'append', 'incremental'
)
# Run the data sling job
try:
result = run(source_table, target_table)
print(f"Sling job completed. Rows replicated: {result.rows_replicated}")
except Exception as e:
print(f"Sling job failed: {e}")
# Example of retrieving connection by name if already added to a global registry (e.g., via CLI or config file)
# connection = Connection.get_connection('my_postgres')