{"id":2393,"library":"asynch","title":"Asynchronous ClickHouse Driver (asynch)","description":"asynch is an asynchronous ClickHouse Python driver with native TCP interface support. It reuses many features from `clickhouse-driver` and adheres to PEP249. Currently at version 0.3.1, it undergoes active development with a focus on providing a robust asyncio-compatible interface for ClickHouse interactions.","status":"active","version":"0.3.1","language":"en","source_language":"en","source_url":"https://github.com/long2ice/asynch.git","tags":["asyncio","clickhouse","database","driver","tcp","native-protocol"],"install":[{"cmd":"pip install asynch","lang":"bash","label":"Basic Installation"},{"cmd":"pip install asynch[compression]","lang":"bash","label":"With `clickhouse-cityhash` for compression"}],"dependencies":[{"reason":"Enables transport compression.","package":"clickhouse-cityhash","optional":true}],"imports":[{"symbol":"Connection","correct":"from asynch import Connection"},{"symbol":"Pool","correct":"from asynch import Pool"},{"note":"Cursor classes are found in the `asynch.cursors` submodule.","symbol":"Cursor","correct":"from asynch.cursors import Cursor"},{"note":"Cursor classes are found in the `asynch.cursors` submodule.","symbol":"DictCursor","correct":"from asynch.cursors import DictCursor"},{"note":"The `connect` function was removed in v0.3.0; use `async with Connection(...)` instead.","wrong":"from asynch import connect","symbol":"connect","correct":"from asynch import Connection # Use Connection class directly"},{"note":"The `create_pool` function was removed in v0.3.0; use `async with Pool(...)` instead.","wrong":"from asynch import create_pool","symbol":"create_pool","correct":"from asynch import Pool # Use Pool class directly"}],"quickstart":{"code":"import asyncio\nfrom asynch import Connection\nfrom asynch.cursors import DictCursor\nimport os\n\nasync def main():\n    # Connect using DSN parameters\n    async with Connection(\n        user=os.environ.get('CH_USER', 'default'),\n        password=os.environ.get('CH_PASSWORD', ''),\n        host=os.environ.get('CH_HOST', '127.0.0.1'),\n        port=int(os.environ.get('CH_PORT', 9000)),\n        database=os.environ.get('CH_DATABASE', 'default'),\n    ) as conn:\n        print(f\"Connected to ClickHouse: {conn.opened}\")\n\n        # Create a table\n        async with conn.cursor() as cursor:\n            await cursor.execute(\n                \"CREATE TABLE IF NOT EXISTS test_table (id UInt64, value String) ENGINE = MergeTree ORDER BY id\"\n            )\n            print(\"Table 'test_table' created or already exists.\")\n\n            # Insert data\n            await cursor.execute(\n                \"INSERT INTO test_table (id, value) VALUES\",\n                [[1, 'hello'], [2, 'world']]\n            )\n            print(\"Data inserted.\")\n\n        # Select data using DictCursor\n        async with conn.cursor(cursor=DictCursor) as cursor:\n            await cursor.execute(\"SELECT id, value FROM test_table ORDER BY id\")\n            result = await cursor.fetchall()\n            print(f\"Fetched data: {result}\")\n            \n        # Clean up (optional)\n        async with conn.cursor() as cursor:\n            await cursor.execute(\"DROP TABLE IF EXISTS test_table\")\n            print(\"Table 'test_table' dropped.\")\n\nif __name__ == \"__main__\":\n    # Example environment variables (replace with your ClickHouse instance details)\n    # os.environ['CH_USER'] = 'my_user'\n    # os.environ['CH_PASSWORD'] = 'my_password'\n    # os.environ['CH_HOST'] = 'localhost'\n    # os.environ['CH_PORT'] = '9000'\n    # os.environ['CH_DATABASE'] = 'my_db'\n    \n    try:\n        asyncio.run(main())\n    except Exception as e:\n        print(f\"An error occurred: {e}\")","lang":"python","description":"This quickstart demonstrates how to establish a connection to a ClickHouse server, create a table, insert data, and fetch results using `asynch`. It showcases the use of `async with` for managing connections and cursors, including `DictCursor` for dictionary-like row access. Environment variables are used for connection details for security."},"warnings":[{"fix":"Replace `await asynch.connect(...)` with `async with Connection(...) as conn:`.","message":"The top-level `asynch.connect()` function has been removed. Direct instantiation and usage of `Connection` within an `async with` statement is now required.","severity":"breaking","affected_versions":">=0.3.0"},{"fix":"Use `Connection.opened` instead of `Connection.connected`.","message":"The `Connection.connected` property, used to check connection status, has been renamed.","severity":"breaking","affected_versions":">=0.3.0"},{"fix":"Replace `await create_pool(...)` with `async with Pool(...) as pool:`.","message":"The `asynch.pool.create_pool()` function has been removed. Connection pooling should now be managed directly using the `Pool` class.","severity":"breaking","affected_versions":">=0.3.0"},{"fix":"Wrap `Connection` and cursor operations in `async with` statements to leverage asynchronous context management.","message":"Always use `async with Connection(...)` and `async with conn.cursor(...)` to ensure connections and cursors are properly managed and closed. Failing to do so can lead to resource leaks and unclosed connections, especially under heavy load.","severity":"gotcha","affected_versions":"All"},{"fix":"Identify and refactor blocking calls. Use `await` with async-compatible libraries (like `asynch`) and for CPU-bound tasks, consider `asyncio.to_thread()` or `loop.run_in_executor()`.","message":"Blocking the asyncio event loop with synchronous I/O or long-running CPU-bound tasks within an async function can severely degrade performance and responsiveness of your application. Ensure all I/O operations are truly asynchronous or offloaded to a thread/process pool.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}