{"id":232,"library":"rq","title":"RQ (Redis Queue)","description":"Simple Python job queue backed by Redis or Valkey. Current version is 2.7.0. Requires Python >=3.9, Redis >=5 or Valkey >=7.2. Much simpler than Celery — no broker config, just a Redis connection. Key API change: job.result property removed in 1.12, replaced by job.return_value(). job.get_status() now returns a JobStatus enum, not a string.","status":"active","version":"2.7.0","language":"python","source_language":"en","source_url":"https://python-rq.org/","tags":["task-queue","redis","workers","async","background-jobs","distributed"],"install":[{"cmd":"pip install rq","lang":"bash","label":"Standard"}],"dependencies":[{"reason":"Required. redis-py 6.0.0 is explicitly blocked due to bugs. Installed automatically.","package":"redis>=4.0.0,!=6.0.0","optional":false},{"reason":"Required for CLI. Installed automatically.","package":"click>=5.0","optional":false}],"imports":[{"note":"job.result property was removed in rq 1.12.0 — use job.return_value() instead. job.get_status() returns a JobStatus enum since rq 1.x — compare with JobStatus.FINISHED not the string 'finished'.","wrong":"# job.result removed in rq 1.12 — AttributeError on modern rq:\nprint(job.result)\n\n# String comparison with job.get_status() broken — it returns enum now:\nif job.get_status() == 'finished':  # always False in rq >= 1.x\n    pass","symbol":"Queue","correct":"from redis import Redis\nfrom rq import Queue\n\n# Connection required at Queue creation time\nredis_conn = Redis(host='localhost', port=6379, db=0)\nq = Queue(connection=redis_conn)\n\n# Functions must be importable — define in a module, not __main__\nfrom myapp.tasks import process_data\njob = q.enqueue(process_data, arg1, arg2)\n\n# Get result (rq >= 1.12)\nresult = job.return_value()  # None until job completes\n\n# Check status — returns JobStatus enum, not string\nfrom rq.job import JobStatus\nstatus = job.get_status()\nif status == JobStatus.FINISHED:\n    print(job.return_value())"}],"quickstart":{"code":"# tasks.py — functions must be in an importable module\ndef add(x, y):\n    return x + y\n\ndef send_email(to, subject, body):\n    # ... email logic\n    return True\n\n\n# enqueue.py — enqueue jobs\nfrom redis import Redis\nfrom rq import Queue\nfrom tasks import add\n\nredis_conn = Redis()\nq = Queue(connection=redis_conn)\n\n# Enqueue\njob = q.enqueue(add, 4, 6)\nprint('Job ID:', job.id)\n\n# Enqueue with options\njob2 = q.enqueue(\n    add, 10, 20,\n    job_timeout=300,    # seconds before job is killed\n    result_ttl=500,     # seconds to keep result in Redis\n    retry=3             # retry on failure\n)\n\n# Check result (after worker runs)\nimport time\ntime.sleep(1)\nprint(job.return_value())  # 10\nprint(job.get_status())    # JobStatus.FINISHED\n\n# --- Start worker in separate terminal ---\n# rq worker","lang":"python","description":"Start Redis first, then run worker: rq worker. Functions must be in importable modules."},"warnings":[{"fix":"Replace job.result with job.return_value(). Note it returns None until the job completes.","message":"job.result property removed in rq 1.12.0. Accessing job.result raises AttributeError. All tutorials and LLM-generated code using job.result are broken.","severity":"breaking","affected_versions":">= 1.12"},{"fix":"from rq.job import JobStatus; if job.get_status() == JobStatus.FINISHED: ... Or use job.is_finished, job.is_failed, job.is_started properties.","message":"job.get_status() returns a JobStatus enum (e.g. JobStatus.FINISHED) not a string ('finished'). Comparing with strings like if job.get_status() == 'finished' always evaluates to False.","severity":"breaking","affected_versions":">= 1.0"},{"fix":"Pin rq<2.0 for Python 3.8 environments.","message":"Python 3.8 support dropped. Minimum is Python 3.9.","severity":"breaking","affected_versions":">= 2.x"},{"fix":"Pin redis!=6.0.0 in requirements. Use redis>=4.0.0,!=6.0.0 or upgrade to a later redis-py patch once fixed.","message":"redis-py 6.0.0 is explicitly blocked — rq will refuse to install with redis==6.0.0 due to critical incompatibilities. Use redis>=4.0.0,!=6.0.0.","severity":"breaking","affected_versions":"all"},{"fix":"Define task functions in separate module files (e.g. tasks.py). The worker imports them by module path.","message":"Enqueued functions must be importable by the worker process. Functions defined in __main__ or interactively (notebooks, scripts run directly) cannot be pickled and will raise PicklingError.","severity":"gotcha","affected_versions":"all"},{"fix":"Start worker in a separate terminal: rq worker. Or use WorkerPool for multiple workers: from rq import WorkerPool; WorkerPool(queues=[q], connection=redis_conn).start()","message":"Workers must be started in a separate process. Running rq worker in the same process as enqueuers causes deadlocks. Workers run: rq worker [queue_name]","severity":"gotcha","affected_versions":"all"},{"fix":"from rq import SpawnWorker; SpawnWorker(queues=[q], connection=redis_conn).work(). Or use SimpleWorker for testing (no fork/spawn, runs in-process).","message":"On Windows and macOS, the default Worker uses fork() which is not available. Use SpawnWorker instead, which uses multiprocessing.spawn.","severity":"gotcha","affected_versions":">= 1.16"}],"env_vars":null,"last_verified":"2026-05-12T12:08:48.704Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Install the Redis Python client: `pip install redis`","cause":"The `rq` library requires the `redis` Python client library as a dependency, but it is not installed in the current environment.","error":"ModuleNotFoundError: No module named 'redis'"},{"fix":"Replace `job.result` with `job.return_value()`.\n\n```python\n# Old code: result = job.result\n# New code:\nresult = job.return_value()\n```","cause":"The `job.result` property was removed in RQ version 1.12; you should now use `job.return_value()` to retrieve the job's return value.","error":"AttributeError: 'Job' object has no attribute 'result'"},{"fix":"Ensure your Redis server is running and accessible at the specified host and port (default is `localhost:6379`). You may need to start the Redis server (e.g., `redis-server`) or verify your `REDIS_URL` / `connection` parameters.","cause":"The RQ client or worker is unable to connect to the Redis server, likely because Redis is not running or is configured to listen on a different host/port.","error":"redis.exceptions.ConnectionError: Error 111 connecting to 127.0.0.1:6379. Connection refused."},{"fix":"Compare the status with members of the `JobStatus` enum or explicitly convert to a string using `str(job.get_status().value)` if a string representation is truly needed.\n\n```python\nfrom rq.job import JobStatus\n\n# Old code: if job.get_status().lower() == 'finished':\n# New code:\nif job.get_status() == JobStatus.FINISHED:\n    pass\n```","cause":"In RQ versions >= 1.12, `job.get_status()` returns a `JobStatus` Enum member, which does not have string methods like `lower()`.","error":"AttributeError: 'JobStatus' object has no attribute 'lower'"},{"fix":"Activate your virtual environment where `rq` is installed (e.g., `source venv/bin/activate` or `.\\venv\\Scripts\\activate`) before running `rq worker`. Alternatively, ensure `rq` is installed globally or in an environment whose `bin` directory is in your PATH.","cause":"The `rq` command-line utility is not found in the system's PATH. This often occurs if `rq` was installed in a virtual environment that is not activated, or if the installation failed.","error":"rq: command not found"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":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":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.32,"mem_mb":10.3,"disk_size":"24.7M"},{"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.23,"mem_mb":10.3,"disk_size":"25M"},{"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.45,"mem_mb":11.9,"disk_size":"27.8M"},{"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.34,"mem_mb":11.9,"disk_size":"28M"},{"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.61,"mem_mb":11.9,"disk_size":"19.4M"},{"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.61,"mem_mb":11.9,"disk_size":"20M"},{"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.59,"mem_mb":12,"disk_size":"19.0M"},{"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.55,"mem_mb":12,"disk_size":"19M"},{"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.27,"mem_mb":9.7,"disk_size":"23.5M"},{"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.23,"mem_mb":9.7,"disk_size":"24M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}