{"id":931,"library":"pyexasol","title":"pyexasol Exasol Python Driver","description":"pyexasol is the officially supported Python connector for Exasol, designed for high-performance data handling with low overhead, fast HTTP transport, and compression. It provides an API for parallel data stream processing, offering significant performance improvements over ODBC/JDBC solutions, especially with `pandas`, `parquet`, and `polars`. The library is actively maintained with a regular release cadence, often seeing monthly or bi-monthly updates.","status":"active","version":"2.1.0","language":"python","source_language":"en","source_url":"https://github.com/exasol/pyexasol","tags":["database","exasol","sql","driver","etl","data-warehousing","websocket"],"install":[{"cmd":"pip install pyexasol","lang":"bash","label":"Install core library"},{"cmd":"pip install pyexasol[pandas,pyarrow,polars,orjson]","lang":"bash","label":"Install with common optional dependencies"}],"dependencies":[{"reason":"Required for secure connections (TLS/SSL certificate validation and RSA operations). Replaced the 'rsa' dependency in v2.0.0.","package":"cryptography","optional":false},{"reason":"Core dependency for the WebSocket protocol-based communication with Exasol.","package":"websocket-client","optional":false},{"reason":"Optional, for `export_to_pandas` and `import_from_pandas` functionality.","package":"pandas","optional":true},{"reason":"Optional, for `export_to_parquet` and `import_from_parquet` functionality.","package":"pyarrow","optional":true},{"reason":"Optional, for integration with Polars DataFrames.","package":"polars","optional":true},{"reason":"Optional, for faster JSON serialization/deserialization.","package":"orjson","optional":true}],"imports":[{"note":"While `pyexasol.connect()` is a common entry point, `ExaConnection` is the primary class for direct interaction and better type hinting.","wrong":"import pyexasol; pyexasol.ExaConnection()","symbol":"ExaConnection","correct":"from pyexasol import ExaConnection"}],"quickstart":{"code":"import os\nfrom pyexasol import ExaConnection\n\n# Replace with your Exasol connection details or environment variables\nEXASOL_HOST = os.environ.get('EXASOL_HOST', '127.0.0.1')\nEXASOL_PORT = os.environ.get('EXASOL_PORT', '8563')\nEXASOL_USER = os.environ.get('EXASOL_USER', 'sys')\nEXASOL_PASSWORD = os.environ.get('EXASOL_PASSWORD', 'exasol')\n\ntry:\n    # Connect to the Exasol database\n    # For production, ensure proper SSL options and fingerprint are used\n    # For local/testing without certs, add: websocket_sslopt={'check_hostname': False, 'verify_mode': 0}\n    # See warnings for v1.0.0 regarding strict certificate verification defaults.\n    con = ExaConnection(\n        dsn=f\"{EXASOL_HOST}:{EXASOL_PORT}\",\n        user=EXASOL_USER,\n        password=EXASOL_PASSWORD\n    )\n    print(\"Successfully connected to Exasol.\")\n\n    # Execute a DDL statement\n    con.execute(\"CREATE SCHEMA IF NOT EXISTS MY_SCHEMA\")\n    con.execute(\"OPEN SCHEMA MY_SCHEMA\")\n\n    # Execute a DML statement\n    con.execute(\"CREATE OR REPLACE TABLE my_table (id INT, name VARCHAR(100))\")\n    con.execute(\"INSERT INTO my_table VALUES (1, 'Alice'), (2, 'Bob')\")\n\n    # Fetch data\n    stmt = con.execute(\"SELECT * FROM my_table ORDER BY id\")\n    results = stmt.fetchall()\n    print(\"Fetched results:\", results)\n\n    # Fetch data into a pandas DataFrame (requires `pyexasol[pandas]`)\n    # import pandas as pd\n    # df = con.export_to_pandas(\"SELECT * FROM my_table\")\n    # print(\"Fetched into DataFrame:\\n\", df)\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    if 'con' in locals() and con.is_connected():\n        con.close()\n        print(\"Connection closed.\")","lang":"python","description":"This quickstart demonstrates how to establish a connection to an Exasol database, execute DDL and DML statements, and fetch results. It highlights the use of `ExaConnection` and basic SQL operations. For local testing without valid SSL certificates, you might need to adjust `websocket_sslopt` as noted in the code comments. Credentials should ideally be managed via environment variables or a secure configuration."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or newer.","message":"Python 3.9 support was dropped in PyExasol v2.0.0. Projects using Python 3.9 or older must upgrade their Python version to >=3.10 to use PyExasol v2.0.0 or later.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `export_params['with_column_names']` is explicitly set to `True` or `False`.","message":"The `export_params['with_column_names']` parameter for export functions (e.g., `export_to_pandas`) now strictly requires a boolean value. Prior to v2.0.0, its mere presence would be interpreted as `True` regardless of the assigned value.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"For production, provide valid SSL certificates via `websocket_sslopt={'ca_certs': 'path/to/cert.pem'}` or use server fingerprints. For development/testing on untrusted networks, consider `websocket_sslopt={'check_hostname': False, 'verify_mode': 0}` (use with caution and never in production).","message":"From PyExasol v1.0.0, strict certificate verification became the default behavior for `pyexasol.connect()` and `ExaConnection`. This changes the default `websocket_sslopt=None` from effectively `{'cert_reqs': ssl.CERT_NONE}` to `{'cert_reqs': ssl.CERT_REQUIRED}`, potentially causing `SSL: CERTIFICATE_VERIFY_FAILED` errors for users not explicitly configuring SSL options. Version 1.0.1 introduced a partial mitigation for fingerprint users.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Ensure the `dst` directory is empty, doesn't exist, or explicitly set `callback_params={'existing_data_behavior': 'overwrite_or_ignore'}` (or 'delete_matching') when calling `export_to_parquet`.","message":"When using `export_to_parquet`, the destination directory (dst) by default must be empty or not exist. If it exists and contains files, an exception may be raised unless `callback_params['existing_data_behavior']` is set to 'overwrite_or_ignore' or 'delete_matching'.","severity":"gotcha","affected_versions":">=1.2.0"},{"fix":"For critical data type preservation, inspect column types after import. Use `callback_params` to pass custom `dtype` arguments to `pandas.read_csv` if necessary, or use `stmt.fetchall()` and manually construct a DataFrame with explicit dtypes.","message":"When exporting data to pandas using `export_to_pandas`, data types might not be perfectly preserved due to differences in Exasol and pandas/NumPy type systems (e.g., Exasol's exact decimals or large integers may map to floats or objects in pandas, potentially losing precision). The underlying mechanism uses CSV export/import.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade to v2.1.0 or later for enhanced error diagnostics in import/export operations involving callbacks. For older versions, examine logs from HTTP and SQL threads for more context.","message":"PyExasol v2.1.0 improved error reporting for `import_from_callback` and `export_to_callback` by wrapping exceptions from various internal threads. Earlier versions might have provided less clear error messages during data transfer failures, making debugging harder.","severity":"gotcha","affected_versions":"<2.1.0"}],"env_vars":null,"last_verified":"2026-05-12T21:25:14.921Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"pip install pyexasol","cause":"The 'pyexasol' package is not installed in the Python environment where the code is being executed.","error":"ModuleNotFoundError: No module named 'pyexasol'"},{"fix":"Verify the DSN (host and port), check network connectivity (e.g., using 'telnet <host> 8563'), ensure the Exasol database is running, and confirm the client's IP address is allow-listed if connecting to Exasol SaaS.","cause":"The client machine cannot establish a network connection to the Exasol database, often due to an incorrect DSN (host or port), firewall restrictions, or the database being offline.","error":"ExaConnectionFailedError: Could not connect to Exasol"},{"fix":"Explicitly set `encryption=True` in the `pyexasol.connect()` call: `pyexasol.connect(dsn='...', user='...', password='...', encryption=True)`.","cause":"The Exasol database is configured to only accept encrypted connections, but the pyexasol client is attempting to connect without encryption enabled.","error":"OperationalError: database error [08004] Connection exception - Client connection must be encrypted."},{"fix":"Update OpenSSL on the client machine, ensure proper TLS/SSL certificate setup (e.g., using trusted CA certificates or fingerprint verification), or, for testing purposes, disable certificate verification (though this is not recommended for production).","cause":"An issue with the SSL/TLS handshake between the client and the Exasol server, often due to an outdated OpenSSL version, invalid certificates, or network intermediaries interfering with the SSL connection.","error":"ssl.SSLEOFError: EOF occurred in violation of protocol"},{"fix":"Upgrade the `pyexasol` package to version `0.3.23` or higher using `pip install --upgrade pyexasol`.","cause":"This error typically occurred on Windows systems in older pyexasol versions (before 0.3.23) when using `export_to_pandas`, due to Python's `multiprocessing` module's limitations in serializing file-like objects across processes.","error":"TypeError: cannot serialize '_io.FileIO' object"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"2.2.1","cli_name":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":6.9,"disk_size":"35.9M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":6.8,"disk_size":"34.9M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":6.9,"disk_size":"567.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":6.8,"disk_size":"528.2M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.7,"import_time_s":0.12,"mem_mb":6.9,"disk_size":"36M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":6.8,"disk_size":"35M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":12.9,"import_time_s":0.11,"mem_mb":6.9,"disk_size":"535M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":6.8,"disk_size":"497M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.28,"mem_mb":7.8,"disk_size":"38.3M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.31,"mem_mb":7.7,"disk_size":"37.2M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.27,"mem_mb":7.8,"disk_size":"592.9M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.32,"mem_mb":7.7,"disk_size":"553.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.4,"import_time_s":0.25,"mem_mb":7.8,"disk_size":"39M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.7,"disk_size":"38M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":12.6,"import_time_s":0.25,"mem_mb":7.8,"disk_size":"560M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.24,"mem_mb":7.7,"disk_size":"521M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.5,"disk_size":"30.0M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.24,"mem_mb":7.4,"disk_size":"28.9M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.5,"disk_size":"577.0M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.4,"disk_size":"537.4M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.2,"import_time_s":0.23,"mem_mb":7.5,"disk_size":"30M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.4,"disk_size":"29M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":12,"import_time_s":0.24,"mem_mb":7.5,"disk_size":"544M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.24,"mem_mb":7.4,"disk_size":"506M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.9,"disk_size":"29.7M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.8,"disk_size":"28.6M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.9,"disk_size":"575.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":7.8,"disk_size":"536.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":2.2,"import_time_s":0.22,"mem_mb":7.9,"disk_size":"30M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.8,"disk_size":"29M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":12.3,"import_time_s":0.23,"mem_mb":7.9,"disk_size":"543M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":7.8,"disk_size":"504M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":5.9,"disk_size":"37.6M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.15,"mem_mb":5.9,"disk_size":"36.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":1,"wheel_type":null,"failure_reason":"build_error","install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"pandas,pyarrow,polars,orjson","exit_code":1,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":null,"mem_mb":null,"disk_size":null},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.4,"import_time_s":0.12,"mem_mb":5.9,"disk_size":"38M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":5.9,"disk_size":"37M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":14.8,"import_time_s":0.11,"mem_mb":5.9,"disk_size":"471M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"pandas,pyarrow,polars,orjson","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":5.9,"disk_size":"470M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}