{"id":7907,"library":"aiocron","title":"aiocron: Crontabs for asyncio","description":"aiocron is a Python library that enables scheduling asynchronous functions using crontab-like syntax within an asyncio event loop. It provides a decorator for coroutines, making it straightforward to define recurring tasks. Currently at version 2.1, the library has a moderate release cadence, with notable breaking changes between its 1.x and 2.x major versions.","status":"active","version":"2.1","language":"en","source_language":"en","source_url":"https://github.com/gawel/aiocron/","tags":["asyncio","cron","scheduler","task scheduling","event loop"],"install":[{"cmd":"pip install aiocron","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Used for parsing cron expressions in aiocron versions 2.0 and above. It replaced 'croniter'.","package":"cronsim"}],"imports":[{"note":"CoroCron is part of a different library (AioCron) and not aiocron. The main scheduling decorator in aiocron is 'crontab'.","wrong":"import CoroCron","symbol":"crontab","correct":"from aiocron import crontab"}],"quickstart":{"code":"import aiocron\nimport asyncio\nimport datetime\n\nasync def my_scheduled_task():\n    \"\"\"A simple asynchronous task.\"\"\"\n    current_time = datetime.datetime.now().strftime('%H:%M:%S')\n    print(f\"Hello from scheduled task! Current time: {current_time}\")\n\nasync def main():\n    # Schedule 'my_scheduled_task' to run every minute using the crontab decorator.\n    # By default, start=True, so it begins scheduling immediately.\n    @aiocron.crontab('* * * * *')\n    async def run_my_task():\n        await my_scheduled_task()\n\n    print(\"aiocron scheduler started. Task 'run_my_task' will run every minute.\")\n    # Keep the asyncio event loop running indefinitely for scheduled tasks.\n    await asyncio.get_event_loop().run_forever()\n\nif __name__ == \"__main__\":\n    try:\n        asyncio.run(main())\n    except KeyboardInterrupt:\n        print(\"\\nScheduler stopped by user.\")","lang":"python","description":"This quickstart demonstrates how to schedule an asynchronous function to run every minute using the `@aiocron.crontab` decorator. The `main` function sets up the scheduler and then keeps the asyncio event loop running indefinitely with `asyncio.get_event_loop().run_forever()` to ensure tasks are executed."},"warnings":[{"fix":"Review your cron expressions for compatibility with the `cronsim` library's syntax. Refer to `cronsim` documentation for supported formats. If strict `croniter` compatibility is required, pin your `aiocron` dependency to `<2.0`.","message":"Version 2.0 and later of aiocron switched its underlying cron expression parsing library from 'croniter' to 'cronsim'. This is a breaking change as specific nuances in cron expression interpretation might differ, potentially causing existing schedules to behave unexpectedly or fail validation.","severity":"breaking","affected_versions":"2.0+"},{"fix":"Ensure the asyncio event loop is properly started and kept alive for the duration you intend your cron jobs to run, typically using `asyncio.get_event_loop().run_forever()` or a long-running `asyncio.run()` of a main coroutine. Always wrap the logic within your scheduled coroutines in `try...except` blocks to prevent unhandled exceptions from crashing the event loop or silently failing tasks.","message":"aiocron operates within an asyncio event loop. Improper handling or termination of the event loop can lead to scheduled tasks not running, unexpected exits, or unhandled exceptions in background tasks. This is particularly common when integrating with other async libraries (e.g., discord.py) that manage their own event loops or when a top-level `asyncio.run()` exits prematurely.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade your Python environment to 3.9 or higher to use aiocron 2.x. If you must use Python 3.7 or 3.8, you will need to pin your aiocron dependency to a compatible 1.x version (e.g., `aiocron<2.0`).","message":"aiocron versions 2.x and above have dropped support for Python 3.7 and 3.8. Attempting to install or run these versions on unsupported Python interpreters will result in errors.","severity":"deprecated","affected_versions":"2.x+"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"If your code directly imports 'croniter', you need to either remove that import if it's no longer necessary with aiocron 2.x, or adjust to use 'cronsim'. If you are relying on older aiocron behavior, consider pinning your aiocron version to `<2.0`.","cause":"You are using aiocron version 2.0 or later, which has replaced 'croniter' with 'cronsim' for cron expression parsing. Your code or an indirect dependency might be trying to access 'croniter'.","error":"ModuleNotFoundError: No module named 'croniter'"},{"fix":"Ensure your main application entry point starts and keeps the event loop running, commonly with `asyncio.get_event_loop().run_forever()` within a `asyncio.run()` block, or by letting `asyncio.run()` manage the top-level async function that contains your aiocron setups. Also, add `try...except` blocks within your scheduled coroutines to catch and log exceptions, preventing them from silently breaking the loop.","cause":"This typically occurs because the asyncio event loop required by aiocron was not started, was stopped prematurely, or a scheduled coroutine raised an unhandled exception.","error":"RuntimeError: no running event loop (or: Task exception was never retrieved)"},{"fix":"Verify that any function decorated with `@aiocron.crontab` is indeed an `async def` function. If you set `start=False` in the decorator (e.g., `@aiocron.crontab('* * * * *', start=False)`), you must manually start the job by calling `.start()` on the returned crontab object: `my_scheduled_job = run_my_task; my_scheduled_job.start()`.","cause":"This error often indicates that the function decorated with `@aiocron.crontab` is not defined as an `async def` coroutine, or if `start=False` was used, the `.start()` method was not explicitly called on the returned crontab object.","error":"TypeError: object NoneType can't be used in 'await' expression (or: AttributeError: 'NoneType' object has no attribute 'start')"}]}