Autarkia-Io
长跑程序的原子文件 IO · Atomic file I/O for long-running agents
中文
崩溃安全的写入、Windows 文件占用重试、可选 fsync、sync/async 双套 API,以及从 LLM 输出里抠 JSON。
来自在单台 Windows 机器上持续持久化状态数月的 Autarkia agent 运行时。整个系列见组件库路线图。
为什么
open(path, "w") 不是一种持久化策略:
- 截断窗口:以写模式打开会先清空文件,新字节还没落盘,崩溃或断电就留下一个空文件。
- 临时名竞争:固定的
.tmp名字在线程和 asyncio 任务之间撞车,两个写入方替换同一个临时文件,其中一个的数据就没了。 - Windows 文件锁:杀毒软件和搜索索引器会短暂占用文件,
os.replace抛WinError 5或32——重试一次就能过。 - 缓冲区会骗你:没有
fsync,操作系统可能确认了一次其实没到磁盘的写入。 - 模型会给 JSON 包壳:代码块、解释文字、模板里带出来的双层花括号,甚至直接拒答。
安装
pip install autarkia-io
# 可选的异步文件后端
pip install "autarkia-io[async]"
没装 aiofiles 时,异步函数在工作线程里跑同步实现。
快速开始
from autarkia_io import safe_json_dump, safe_json_load, safe_write_text
safe_json_dump({"mood": "calm"}, "data/state.json")
state = safe_json_load("data/state.json", default={})
safe_write_text("line 1\nline 2", "data/notes.txt", use_fsync=True)
异步:
from autarkia_io import async_safe_json_dump, async_safe_json_load
await async_safe_json_dump({"a": 1}, "data/state.json")
state = await async_safe_json_load("data/state.json", default={})
从模型回复里取 JSON:
from autarkia_io import extract_json_object, looks_like_refusal, unwrap_redundant_brackets
extract_json_object('好的:```json\n{"mood": "happy"}\n```')
# {"mood": "happy"}
extract_json_object('{{"people": [{{"name": "a"}}]}}')
# 整串都被包了一层时,先 unwrap_redundant_brackets
looks_like_refusal("抱歉,我无法完成这个请求") # True
接口一览
| 函数 | 保证 |
|---|---|
safe_write_text / safe_json_dump |
临时文件 + os.replace,每次调用唯一 |
retry_replace |
WinError 5/32 / EACCES 的指数退避重试 |
cleanup_stale_temp_files |
清理 5 分钟以上的孤儿临时文件 |
safe_read_text / safe_json_load |
缺失或损坏时返回默认值 |
async_* |
同样的保证,aiofiles 或线程回退 |
extract_json_object |
第一个配平的 object,否则第一个数组 |
unwrap_redundant_brackets |
剥掉从提示模板抄来的 {{...}} |
looks_like_refusal |
区分「拒答」与「JSON 写坏了」 |
设计说明
- 重试有上限:同步约 25 秒、异步约 2 秒,之后错误照常抛出。
- 最终还是
PermissionError时回退:同步写入退回直接写,避免数据丢失;这是文档化的行为,不是静默降级。 - 没有全局状态:路径全是参数,不 import 任何配置。
- 测试确定性:
retry_replace接受sleep=,重试路径测试瞬间跑完。
系列与链接
- 项目页:https://qishihao.icu/projects/autarkia
- 运行时仓库:https://github.com/hakituo/Autarkia
- 本包:https://github.com/hakituo/Autarkia-Io
- 组件库路线图:https://github.com/hakituo/Autarkia-tool/blob/main/ROADMAP.md
- 作者:Shihao Qi — https://qishihao.icu
许可
MIT
English
Crash-safe writes, Windows lock retries, optional fsync, sync + async APIs, and resilient JSON extraction from LLM output.
Extracted from the Autarkia agent runtime, which has persisted state on a single Windows machine for months. See the component roadmap.
Why
Naive open(path, "w") is not a persistence strategy:
- Truncation window. Opening for write empties the file before new bytes land. A crash or power loss leaves an empty file.
- Temp-name races. A fixed
.tmpname collides between threads and asyncio tasks. Two writers replace the same temp file and one loses its data. - Windows locks. Antivirus and the search indexer briefly hold files.
os.replacefails withWinError 5or32, which a retry resolves. - Buffers lie. Without
fsync, the OS may acknowledge a write that never reaches disk. - Models wrap JSON. LLMs return JSON inside fences, prose, doubled template braces, or a refusal.
Install
pip install autarkia-io
# optional async file backend
pip install "autarkia-io[async]"
Without aiofiles, async functions run the sync implementation in a worker thread.
Quick start
from autarkia_io import safe_json_dump, safe_json_load, safe_write_text
safe_json_dump({"mood": "calm"}, "data/state.json")
state = safe_json_load("data/state.json", default={})
safe_write_text("line 1\nline 2", "data/notes.txt", use_fsync=True)
Async
from autarkia_io import async_safe_json_dump, async_safe_json_load
await async_safe_json_dump({"a": 1}, "data/state.json")
state = await async_safe_json_load("data/state.json", default={})
JSON from an LLM reply
from autarkia_io import extract_json_object, looks_like_refusal, unwrap_redundant_brackets
extract_json_object('好的:```json\n{"mood": "happy"}\n```')
# {"mood": "happy"}
extract_json_object('{{"people": [{{"name": "a"}}]}}')
# ... use unwrap_redundant_brackets first if the whole string is doubled
looks_like_refusal("抱歉,我无法完成这个请求") # True
Concepts
| Function | What it guarantees |
|---|---|
safe_write_text / safe_json_dump |
temp file + os.replace, unique per call |
retry_replace |
exponential backoff for WinError 5/32 / EACCES |
cleanup_stale_temp_files |
removes orphaned temp files older than 5 minutes |
safe_read_text / safe_json_load |
default value for missing/corrupt data |
async_* |
same guarantees, aiofiles or thread fallback |
extract_json_object |
first balanced object, else first array |
unwrap_redundant_brackets |
strips {{...}} copied from prompt templates |
looks_like_refusal |
distinguishes a refusal from malformed JSON |
Design notes
- Retry is bounded. Sync waits about 25 seconds total; async about 2 seconds. After that, errors surface.
- Fallback on final
PermissionError. The sync write falls back to a direct write so data is not lost when replacement is impossible; this is documented, not silent. - No global state. All paths are arguments; no configuration import.
- Deterministic tests.
retry_replaceacceptssleep=so retry tests run instantly.
The bigger picture
- Project page: https://qishihao.icu/projects/autarkia
- Runtime repository: https://github.com/hakituo/Autarkia
- This package: https://github.com/hakituo/Autarkia-Io
- Roadmap: https://github.com/hakituo/Autarkia-tool/blob/main/ROADMAP.md
- Author: Shihao Qi — https://qishihao.icu
License
MIT
Metadata
Release files for Autarkia-Io 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| autarkia_io-0.1.0.tar.gz | 13.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| autarkia_io-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.7 kB
Release files / autarkia_io-0.1.0.tar.gz
| Download URL | autarkia_io-0.1.0.tar.gz |
|---|---|
| Size | 13.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0710a352668e29199a6245e23e6b5b2845d920492232ad5d9af27ab74c8ef84f
|
|
BLAKE2b-256 checksum How to use checksums |
ea5aac737096033182db7df3fe850805a164d3cc0495ca342c6dc877bf350d69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / autarkia_io-0.1.0-py3-none-any.whl
| Download URL | autarkia_io-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0868d348011da32fcd6017bb7c5cb62fb0caa39a13216902a983ad5dc313b123
|
|
BLAKE2b-256 checksum How to use checksums |
3c31eb2ed17991f4dad067554c8042e9c3e2bb279a87860c1a7637b277ac1cf0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.19 {"installer":{"name":"uv","version":"0.12.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for Autarkia-Io 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.