{"id":4810,"library":"transaction","title":"Python Transaction Management","description":"The `transaction` package provides a generic transaction implementation for Python, offering a two-phase commit protocol. It allows multiple backends (such as ZODB, SQLAlchemy, filesystem, or custom data managers) to participate in a single transaction, ensuring atomicity across diverse storage systems. It also supports savepoints, enabling partial rollbacks. The current version is 5.1, with a release cadence that has seen several major updates over the last few years, maintaining active development.","status":"active","version":"5.1","language":"en","source_language":"en","source_url":"https://github.com/zopefoundation/transaction","tags":["transaction","two-phase commit","data consistency","zopefoundation","atomicity"],"install":[{"cmd":"pip install transaction","lang":"bash","label":"Install latest version"}],"dependencies":[],"imports":[{"symbol":"transaction","correct":"import transaction"}],"quickstart":{"code":"import transaction\n\n# In a real application, 'some_backend_operation()' would interact\n# with a data manager (e.g., ZODB, SQLAlchemy session, or a custom one)\n# which registers itself with the transaction machinery automatically\n# or explicitly.\n# For this example, we'll simulate a backend operation.\n\ndef some_backend_operation(success=True):\n    print(f\"Performing backend operation (success={success})...\")\n    # In a real scenario, this would be where changes are made\n    # to a persistent store via a registered data manager.\n    if not success:\n        raise ValueError(\"Simulated backend error!\")\n    print(\"Backend operation completed.\")\n\ntry:\n    # Code block where operations participating in the transaction occur\n    some_backend_operation(success=True)\n    # If multiple backends are involved, their operations would be here too\n    # e.g., db_session.add(some_object), file_manager.write_data()\n\n    # Commit the transaction if all operations succeed\n    print(\"Attempting to commit transaction...\")\n    transaction.commit()\n    print(\"Transaction committed successfully.\")\nexcept ValueError as e:\n    # Rollback the transaction if any operation fails\n    print(f\"Error: {e}. Rolling back transaction...\")\n    transaction.abort()\n    print(\"Transaction aborted.\")\nexcept Exception as e:\n    print(f\"Unexpected error: {e}. Aborting transaction...\")\n    transaction.abort()","lang":"python","description":"This quickstart demonstrates the basic pattern of using `transaction.commit()` and `transaction.abort()` within a try-except block. In a practical scenario, `some_backend_operation()` would involve one or more data managers (e.g., from ZODB, SQLAlchemy, or a custom implementation) that register themselves with the global transaction manager when modifications are made. The `transaction` library coordinates these data managers to ensure an all-or-nothing outcome using a two-phase commit protocol."},"warnings":[{"fix":"Ensure your Python environment meets the requirements of the `transaction` library version you are using. Upgrade Python to 3.10 or newer for `transaction` 5.1.","message":"Recent major versions have dropped support for older Python versions. Specifically, v4.0 dropped Python 2.7, 3.5, 3.6; v5.0 dropped Python 3.7; and v5.1 dropped Python 3.8, 3.9. Always check the release notes for detailed compatibility.","severity":"breaking","affected_versions":"4.0, 5.0, 5.1"},{"fix":"Migrate your code to use the modern transaction management APIs. Review the official documentation for the updated patterns for data manager integration and `TransactionManager.run` usage.","message":"Version 3.0.0 introduced significant breaking changes by dropping support for legacy transaction APIs, including `Transaction.register()` and older ZODB3-style data managers. The behavior of `TransactionManager.run` also changed, affecting how transactions are committed/aborted after function execution.","severity":"breaking","affected_versions":"3.0.0 and later"},{"fix":"Be aware of thread boundaries. For scenarios requiring explicit transaction scope per request/task, consider using a framework integration (like `pyramid_tm`) or explicitly passing transaction objects, rather than relying solely on the global `transaction.manager` implicit behavior.","message":"The default transaction manager (`transaction.manager`) is typically thread-local. In multi-threaded applications or complex asynchronous contexts, improper management can lead to unexpected state or lost changes if transactions are not correctly demarcated for each thread/task.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Perform irreversible side effects *after* a successful `transaction.commit()`. For blocking operations, restructure your code to move them outside the critical transaction path or use asynchronous patterns where appropriate.","message":"Avoid placing irreversible operations (e.g., external API calls, sending emails, writing to external non-transactional services) or long-running, blocking I/O calls within the scope of a `transaction` block. Transactions hold locks on resources, and such operations can lead to deadlocks, timeouts, or inconsistent states if a rollback becomes necessary.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}