{"id":17748521,"url":"https://github.com/purarue/sqlite_backup","last_synced_at":"2026-01-17T07:29:41.092Z","repository":{"id":44639978,"uuid":"453802352","full_name":"purarue/sqlite_backup","owner":"purarue","description":"a tool to snapshot sqlite databases you don't own","archived":false,"fork":false,"pushed_at":"2026-01-14T20:52:10.000Z","size":83,"stargazers_count":24,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-15T00:55:00.603Z","etag":null,"topics":["database","sqlite","sqlite3"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/sqlite-backup/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purarue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-01-30T21:07:51.000Z","updated_at":"2026-01-14T20:52:00.000Z","dependencies_parsed_at":"2024-10-27T10:27:49.361Z","dependency_job_id":"4043d169-5b10-43a3-b7ab-fd23010f7cb1","html_url":"https://github.com/purarue/sqlite_backup","commit_stats":{"total_commits":46,"total_committers":2,"mean_commits":23.0,"dds":"0.021739130434782594","last_synced_commit":"2e12f471676bc43dcc8bff68f579f3c25cfed4d9"},"previous_names":["seanbreckenridge/sqlite_backup"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/purarue/sqlite_backup","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fsqlite_backup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fsqlite_backup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fsqlite_backup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fsqlite_backup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purarue","download_url":"https://codeload.github.com/purarue/sqlite_backup/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purarue%2Fsqlite_backup/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28504302,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","sqlite","sqlite3"],"created_at":"2024-10-26T10:01:59.063Z","updated_at":"2026-01-17T07:29:41.087Z","avatar_url":"https://github.com/purarue.png","language":"Python","readme":"# sqlite_backup\n\nThis exposes the python stdlib [`sqlite.backup`](https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.backup) function as a library, with a couple extra steps.\n\nThe main purpose for writing this is to copy sqlite databases that you may not own -- perhaps it belongs to an application (e.g., your browser) and is locked since that's currently open, or the OS keeps it open while the computer is active (e.g. Mac with iMessage)\n\n### Features\n\n- Has the option (true by default) to first [safely copy](https://github.com/purarue/sqlite_backup/blob/cbe57a88bc987ca990edfb65b66f04b6d8765a5e/sqlite_backup/core.py#L48-L56) the database from disk to a temporary directory, which is:\n  - useful in case the source is in read-only mode (e.g. in some sort of docker container)\n  - safer if you're especially worried about corrupting or losing data\n- Uses [`Cpython`s Connection.backup](https://github.com/python/cpython/blob/8fb36494501aad5b0c1d34311c9743c60bb9926c/Modules/_sqlite/connection.c#L1716), which directly uses the [underlying Sqlite C code](https://www.sqlite.org/c3ref/backup_finish.html)\n- Performs a [`wal_checkpoint`](https://www.sqlite.org/pragma.html#pragma_wal_checkpoint) and sets `journal_mode=DELETE` after copying to the destination, to remove the WAL (write-ahead log; temporary database file). Typically the WAL is removed when the database is closed, but [particular builds of sqlite](https://sqlite.org/forum/forumpost/1fdfc1a0e7), the [default sqlite installed on mac](https://github.com/purarue/sqlite_backup/issues/9), or sqlite compiled with [`SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE` enabled](https://www.sqlite.org/c3ref/c_dbconfig_enable_fkey.html) or [`SQLITE_FCNTL_PERSIST_WAL`](https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlpersistwal) may prevent that -- so the checkpoint exists to ensure there are no temporary files leftover\n\nIn short, this **prioritizes safety of the data** over performance (temporarily copying data files to `/tmp`) - because we often don't know what the application may be doing while we're copying underlying sqlite databases\n\nThe initial backup function and some tests were extracted out of the [`karlicoss/HPI` `core/sqlite`](https://github.com/karlicoss/HPI/blob/a1f03f9c028df9d1898de2cc14f1df4fa6d8c471/my/core/sqlite.py#L33-L51) module\n\nIf other tools exist to do this, please [let me know!](https://github.com/purarue/sqlite_backup/issues/new)\n\n## Installation\n\nRequires `python3.10+`\n\nTo install with pip, run:\n\n    pip install sqlite_backup\n\n## Usage\n\n```\nUsage: sqlite_backup [OPTIONS] SOURCE_DATABASE DESTINATION\n\n  SOURCE_DATABASE is the database to copy\n\n  DESTINATION is where to write the database. If a directory, uses\n  the SOURCE_DATABASE name. If a file, the directory must exist,\n  and the destination file must not already exist (to prevent\n  possibly overwriting old data)\n\nOptions:\n  --debug                         Increase log verbosity  [default: False]\n  --wal-checkpoint / --no-wal-checkpoint\n                                  After writing to the destination, run a\n                                  checkpoint to truncate the WAL to zero bytes\n                                  [default: wal-checkpoint]\n  --copy-use-tempdir / --no-copy-use-tempdir\n                                  Copy the source database files to a\n                                  temporary directory, then connect to the\n                                  copied files  [default: copy-use-tempdir]\n  --copy-retry INTEGER            If the files change while copying to the\n                                  temporary directory, retry \u003cn\u003e times\n                                  [default: 100]\n  --copy-retry-strict / --no-copy-retry-strict\n                                  Throws an error if this fails to safely copy\n                                  the database files --copy-retry times\n                                  [default: copy-retry-strict]\n  --help                          Show this message and exit.  [default:\n                                  False]\n```\n\nFor usage in python, use the `sqlite_backup` function, see the [docs](./docs/sqlite_backup/index.md)\n\nIf you plan on reading from these backed up databases (and you're not planning on modifying these at all), I would recommend using the [`mode=ro`](https://www.sqlite.org/uri.html#urimode) (readonly) or [`immutable`](https://www.sqlite.org/uri.html#uriimmutable) flags when connecting to the database. In python, like:\n\n```python\nimport sqlite3\nfrom typing import Iterator\n\ndef sqlite_connect(database: str) -\u003e Iterator[sqlite3.Connection]:\n    try:\n        # or for immutable, f\"file:{database}?immutable=1\"\n        with sqlite3.connect(f\"file:{database}?mode=ro\", uri=True) as conn:\n            yield conn\n    finally:\n        conn.close()\n\nwith sqlite_connect(\"/path/to/database\") as conn:\n    conn.execute(\"...\")\n```\n\n### Example\n\n```\nsqlite_backup --debug ~/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite ./firefox.sqlite\n[D 220202 13:00:32 core:110] Source database files: '['/home/username/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite', '/home/username/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite-wal']'\n[D 220202 13:00:32 core:111] Temporary Destination database files: '['/tmp/tmpm2nhl1p3/places.sqlite', '/tmp/tmpm2nhl1p3/places.sqlite-wal']'\n[D 220202 13:00:32 core:64] Copied from '/home/username/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite' to '/tmp/tmpm2nhl1p3/places.sqlite' successfully; copied without file changing: True\n[D 220202 13:00:32 core:64] Copied from '/home/username/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite-wal' to '/tmp/tmpm2nhl1p3/places.sqlite-wal' successfully; copied without file changing: True\n[D 220202 13:00:32 core:240] Running backup, from '/tmp/tmpm2nhl1p3/places.sqlite' to '/home/username/Repos/sqlite_backup/firefox.sqlite'\nBacked up /home/username/.mozilla/firefox/ew9cqpqe.dev-edition-default/places.sqlite to /home/username/Repos/sqlite_backup/firefox.sqlite\n```\n\n### Tests\n\n```bash\ngit clone 'https://github.com/purarue/sqlite_backup'\ncd ./sqlite_backup\npip install '.[testing]'\nmypy ./sqlite_backup\npytest\n```\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurarue%2Fsqlite_backup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurarue%2Fsqlite_backup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurarue%2Fsqlite_backup/lists"}