# Atio ๐ก๏ธ
์์ ํ๊ณ **์์์ ์ธ ํ์ผ ์ฐ๊ธฐ**๋ฅผ ์ง์ํ๋ ๊ฒฝ๋ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
Pandas, Polars, NumPy ๋ฑ ๋ฐ์ดํฐ ๊ฐ์ฒด ์ ์ฅ ์ **ํ์ผ ์์ ์์ด**, **ํธ๋์ญ์
์ฒ๋ผ ์์ ํ๊ฒ ์ฒ๋ฆฌ**ํ ์ ์์ต๋๋ค.
---
## ๐ ์ฃผ์ ๊ธฐ๋ฅ
- โ
์์ ๋๋ ํ ๋ฆฌ ์คํ
์ด์ง ํ **์์์ ํ์ผ ๊ต์ฒด**
- ๐ฆ Pandas, Polars, NumPy ๋ฑ ๋ค์ํ ๋ฐ์ดํฐ ๊ฐ์ฒด ์ง์
- ๐ `_SUCCESS` ํ๋๊ทธ ํ์ผ ์์ฑ โ ์ ์ฅ ์๋ฃ ์ฌ๋ถ ํ์
- ๐ ์คํจ ์ **์๋ณธ ํ์ผ ๋ณด์กด**, ์์ ํ์ผ ์๋ ์ ๋ฆฌ
- ๐งฉ ํ๋ฌ๊ทธ์ธ ์ํคํ
์ฒ๋ก **ํ์ฅ์ฑ ์ข์**
- ๐ **์ฑ๋ฅ ์ง๋จ ๋ก๊น
** โ ๊ฐ ๋จ๊ณ๋ณ ์คํ ์๊ฐ ์ธก์ ๋ฐ ๋ณ๋ชฉ์ ๋ถ์
---
## ๐ ์ฑ๋ฅ ์ง๋จ ๋ก๊น
(NEW!)
Atio๋ ์ด์ **์ฑ๋ฅ ์ง๋จ ๋ก๊น
** ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. `verbose=True` ์ต์
์ ์ฌ์ฉํ๋ฉด ๊ฐ ๋จ๊ณ๋ณ ์คํ ์๊ฐ์ ์ธก์ ํ์ฌ ๋ณ๋ชฉ์ ์ ์ ํํ ํ์
ํ ์ ์์ต๋๋ค.
### ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ (๊ฐ๋จํ ์ ๋ณด๋ง):
```python
import atio as aw
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3]})
# ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ - ๊ฐ๋จํ ์ฑ๊ณต/์คํจ ์ ๋ณด๋ง
aw.write(df, "output.parquet", format="parquet")
```
**์ถ๋ ฅ ์์:**
```
[INFO] ์์ ๋๋ ํ ๋ฆฌ ์์ฑ: /tmp/tmp_xxx
[INFO] ์์ ํ์ผ ๊ฒฝ๋ก: /tmp/tmp_xxx/output.parquet
[INFO] ์ฌ์ฉํ writer: to_parquet (format: parquet)
[INFO] ๋ฐ์ดํฐ ์์ ํ์ผ์ ์ ์ฅ ์๋ฃ: /tmp/tmp_xxx/output.parquet
[INFO] ์์์ ๊ต์ฒด ์๋ฃ: /tmp/tmp_xxx/output.parquet -> output.parquet
[INFO] _SUCCESS ํ๋๊ทธ ํ์ผ ์์ฑ: output.parquet._SUCCESS
[INFO] Atomic write completed successfully (took 0.2359s)
```
### ์์ธ ์ง๋จ ๋ชจ๋ (verbose=True):
```python
# ์์ธํ ์ฑ๋ฅ ์ง๋จ ์ ๋ณด ์ถ๋ ฅ
aw.write(df, "output.parquet", format="parquet", verbose=True)
```
**์ถ๋ ฅ ์์:**
```
[INFO] ์์ ๋๋ ํ ๋ฆฌ ์์ฑ: /tmp/tmp_xxx
[INFO] ์์ ํ์ผ ๊ฒฝ๋ก: /tmp/tmp_xxx/output.parquet
[INFO] ์ฌ์ฉํ writer: to_parquet (format: parquet)
[INFO] ๋ฐ์ดํฐ ์์ ํ์ผ์ ์ ์ฅ ์๋ฃ: /tmp/tmp_xxx/output.parquet
[INFO] ์์์ ๊ต์ฒด ์๋ฃ: /tmp/tmp_xxx/output.parquet -> output.parquet
[INFO] _SUCCESS ํ๋๊ทธ ํ์ผ ์์ฑ: output.parquet._SUCCESS
[DEBUG] Atomic write step timings (SUCCESS): setup=0.0012s, write_call=0.2345s, replace=0.0001s, success_flag=0.0001s, total=0.2359s
```
### ์ค๋ฅ ๋ฐ์ ์ (๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ):
```
[INFO] ์์ ๋๋ ํ ๋ฆฌ ์์ฑ: /tmp/tmp_xxx
[INFO] ์์ ํ์ผ ๊ฒฝ๋ก: /tmp/tmp_xxx/output.parquet
[INFO] ์ฌ์ฉํ writer: to_parquet (format: parquet)
[ERROR] ์์ ํ์ผ ์ ์ฅ ์ค ์์ธ ๋ฐ์: [Errno 28] No space left on device
[INFO] Atomic write failed during write stage (took 0.1246s, error: OSError)
```
### ์ค๋ฅ ๋ฐ์ ์ (verbose=True):
```
[INFO] ์์ ๋๋ ํ ๋ฆฌ ์์ฑ: /tmp/tmp_xxx
[INFO] ์์ ํ์ผ ๊ฒฝ๋ก: /tmp/tmp_xxx/output.parquet
[INFO] ์ฌ์ฉํ writer: to_parquet (format: parquet)
[ERROR] ์์ ํ์ผ ์ ์ฅ ์ค ์์ธ ๋ฐ์: [Errno 28] No space left on device
[DEBUG] Atomic write step timings (ERROR during write): setup=0.0012s, write_call=0.1234s (์คํจ), replace=N/A, success_flag=N/A, total=0.1246s, error_type=OSError
```
**์ธก์ ๋๋ ๋จ๊ณ:**
- `setup`: ์์ ํด๋ ์์ฑ ๋ฐ ์ด๊ธฐ ์ค์
- `write_call`: ์ค์ ๋ฐ์ดํฐ ์ฐ๊ธฐ ํจ์ ํธ์ถ (๋๋ถ๋ถ์ ์๊ฐ ์์)
- `replace`: ์์์ ํ์ผ ๊ต์ฒด
- `success_flag`: _SUCCESS ํ๋๊ทธ ํ์ผ ์์ฑ
- `total`: ์ ์ฒด ์์
์๊ฐ
**์ง์ํ๋ ์ค๋ฅ ์ํฉ:**
- โ
**KeyboardInterrupt**: ์ธํฐ๋ฝํธ ๋ฐ์ ์์ ๊ณผ ์์ ์๊ฐ ํ์
- โ
**๊ถํ ์ค๋ฅ**: ํ์ผ ์์คํ
๊ถํ ๋ฌธ์ ์ง๋จ
- โ
**๋์คํฌ ๊ณต๊ฐ ๋ถ์กฑ**: ์ ์ฅ ๊ณต๊ฐ ๋ถ์กฑ ์ํฉ ์ง๋จ
- โ
**๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ**: ๋ฉ๋ชจ๋ฆฌ ์๋ฐ ์ํฉ ์ง๋จ
- โ
**๋คํธ์ํฌ ์ค๋ฅ**: ๋คํธ์ํฌ ๋๋ผ์ด๋ธ ์ ๊ทผ ๋ฌธ์ ์ง๋จ
- โ
**์ง์ํ์ง ์๋ ํ์**: ์๋ชป๋ ํ์ผ ํ์ ์ง์ ์ ์ง๋จ
- โ
**๋์ ์ ๊ทผ ์ค๋ฅ**: ๋ฉํฐ์ค๋ ๋ฉ ํ๊ฒฝ์์์ ์ถฉ๋ ์ง๋จ
**์ฅ์ :**
- ๐ฏ **์ ํํ ๋ณ๋ชฉ์ ํ์
**: Atio ์ค๋ฒํค๋ vs ์ค์ ์ฐ๊ธฐ ์์
์๊ฐ ๊ตฌ๋ถ
- ๐ง **์ฑ๋ฅ ์ต์ ํ ๊ฐ์ด๋**: ์ด๋ ๋จ๊ณ์์ ์๊ฐ์ด ๋ง์ด ์์๋๋์ง ๋ช
ํํ ํ์
- ๐ **๋๋ฒ๊น
์๊ฐ ๋จ์ถ**: ๋ฌธ์ ์ ์์ธ์ ๋น ๋ฅด๊ฒ ํ์
๊ฐ๋ฅ
- ๐ **์ฑ๋ฅ ๋ชจ๋ํฐ๋ง**: ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ ์ฑ๋ฅ ์ถ์
- ๐จ **์ค๋ฅ ์ง๋จ**: ์คํจ ์ํฉ์์๋ ์ ํํ ์์ธ๊ณผ ๋ฐ์ ์์ ํ์
---
## ๐ง ์ ์ด ๋๊ตฌ๊ฐ ์ ๋ง ์ค์ํ๊ฐ์?
NumPy๋ Pandas๋ ๋ฐ์ดํฐ ๋ถ์์์๋ ์ต์ ์ด์ง๋ง, **ํ์ผ๋ก ์ ์ฅํ ๋๋ ์๋์ ๊ฐ์ ์ํ**์ด ์์ต๋๋ค:
1. **ํ์ผ ์ผ๋ถ๋ง ์ ์ฅ๋์ด ๊นจ์ง ์ ์์** โ ๊ฐ์ ์ข
๋ฃ๋ ์ค๋ฅ ์
2. **๋์ ์ฐ๊ธฐ ์ถฉ๋** โ ๋ฉํฐํ๋ก์ธ์ค ํ๊ฒฝ์์ ํ์ผ์ด ์ํฌ ์ ์์
3. **ํ๋ซํผ ๊ฐ ๋์ ์ฐจ์ด** โ Windows์ Linux/macOS์์ ํ์ผ ์์คํ
๋์์ด ๋ค๋ฆ
AtomicWriter๋ ์์ ํ์ผ์ ์ฐ๊ณ **๋จ์ผ `rename()`/`replace()` ์์
์ผ๋ก ๊ต์ฒด**ํฉ๋๋ค.
์ด ๋ฐฉ์์ **โ์์ ํ ์ ์ฅ๋๊ฑฐ๋ ์ ํ ์ ์ฅ๋์ง ์๋โ** ์์์ฑ(atomicity)์ ๋ณด์ฅํ๋ฉฐ,
- POSIX: `os.replace` (atomic), `fsync`
- Windows: `MoveFileEx`, `Commit`
๋ฅผ ํ์ฉํ์ฌ ํ์ผ์ด **ํญ์ ์ผ๊ด๋ ์ํ**๋ฅผ ์ ์งํ๋๋ก ํฉ๋๋ค :contentReference[oaicite:1]{index=1}.
---
## โ๏ธ ์ค์น
```bash
pip install atomicwriter
## ๐ ๏ธ ์ฌ์ฉ ์์
```python
import atomicwriter as aw
import pandas as pd
df = pd.DataFrame({"a": [1, 2, 3]})
# ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
aw.write(df, "output.parquet", format="parquet")
# โโ ์์ ํ์ผ ์์ฑ โ ์์์ ๊ต์ฒด โ _SUCCESS ์์ฑ
# โโ ์คํจ ์ ์๋ณธ ๋ณด์กด, ์์ ํ์ผ ์๋ ์ ๋ฆฌ
# ์์ธ ์ฑ๋ฅ ์ง๋จ ๋ก๊น
ํ์ฑํ
aw.write(df, "output_verbose.parquet", format="parquet", verbose=True)
# โโ ๊ฐ ๋จ๊ณ๋ณ ์คํ ์๊ฐ ์ธก์ ๋ฐ ๋ก๊ทธ ์ถ๋ ฅ
# ์งํ๋ ํ์์ ํจ๊ป ์ฌ์ฉ
aw.write(df, "output_progress.parquet", format="parquet", show_progress=True)
# โโ ์ค์๊ฐ ์งํ๋ ํ์
# ๋ชจ๋ ์ต์
์กฐํฉ
aw.write(df, "output_full.parquet", format="parquet",
verbose=True, show_progress=True)
# โโ ์ฑ๋ฅ ์ง๋จ + ์งํ๋ ํ์
```
## ๐ก ๋น
๋ฐ์ดํฐ ์ํฌํ๋ก์ฐ์์ ํ์ฉ ์๋๋ฆฌ์ค
| ์๋๋ฆฌ์ค | ํด๊ฒฐ ๋ฐฉ๋ฒ | ์ฅ์ |
|------------------------|-----------------------------|-------------------------|
| Pandas โ CSV ์ ์ฅ | ์์ ํ์ผ์ ๊ธฐ๋ก ํ ๊ต์ฒด | CSV ํ์ผ ๊นจ์ง ๋ฐฉ์ง |
| ๋ฉํฐํ๋ก์ธ์ค ๋ณ๋ ฌ ์ฐ๊ธฐ | atomic replace ๋ฐฉ์ ์ฌ์ฉ | ์ถฉ๋ ์๋ ์์ ์ ์ฅ |
| ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ์์
| ์ ์ฅ ์ฑ๊ณต ์ `_SUCCESS` ํ์ธ | ๋ฐ์ดํฐ ์์ ์ฑ ๋ณด์ฅ |
---
## ๐ ๋น๊ต โ ์ ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํน์ง ์ ๋ฆฌ
### [python-atomicwrites](https://github.com/untitaker/python-atomicwrites)
- ๊ฐํธํ API
- Windows ์ง์
- ํฌ๋ก์ค ํ๋ซํผ ํธํ
### atomicwriter (๋ณธ ํ๋ก์ ํธ)
- โ
๊ฒฝ๋
- โ
ํ๋ฌ๊ทธ์ธ ์ํคํ
์ฒ
- โ
Pandas / Polars / Numpy ๋ฑ ๋ฐ์ดํฐ ๊ฐ์ฒด ์ค์ฌ ์ ์ฅ ์ง์
---
## โ
๋ผ์ด์ ์ค
Apache 2.0 โ ๊ธฐ์
๋ฐ ์ปค๋ฎค๋ํฐ ๋ชจ๋ ์์ ๋กญ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ
---
## โจ ์์ฝ
**AtomicWriter**๋ ๋ถ์๋งํผ ์ค์ํ **โ์ ์ฅโ ๋จ๊ณ๋ฅผ ์์ ํ๊ฒ ์ฒ๋ฆฌ**ํ๋ ๋๊ตฌ์
๋๋ค.
ํนํ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ด ์ค์ํ ํ๊ฒฝ์์
(์: ๋จธ์ ๋ฌ๋ ๋ฐฐ์น, ๋ฉํฐํ๋ก์ธ์ค ๋ถ์, ์ค์ ๋ก๊ทธ ์ ์ฅ ๋ฑ)
**์์ง๋ง ๊ฐ๋ ฅํ ํด๊ฒฐ์ฑ
**์ ์ ๊ณตํฉ๋๋ค.
๐ ์๋๋ฆฌ์ค 1: Pandas CSV ์ ์ฅ ์ค ์์
์ค๋จ
๋ฌธ์ ์ํฉ:
ํ ์ฌ์ฉ์๊ฐ Pandas๋ก ๋์ฉ๋ ๋ถ์ ๊ฒฐ๊ณผ๋ฅผ .csv ํ์ผ๋ก ์ ์ฅํ๋ ์ค, ์์์น ๋ชปํ ์ ์ ์ฐจ๋จ์ด๋ ์ปค๋ ๊ฐ์ ์ข
๋ฃ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๊ฒฐ๊ณผ ํ์ผ์ 50MB ์ค 3MB๋ง ์ ์ฅ๋ ์ฑ ์์๋์๊ณ , ์ดํ ์ฝ๊ธฐ๋ ๋์ง ์์์ต๋๋ค.
AtomicWriter๋ก ํด๊ฒฐ:
์์ ํ์ผ์ ๋จผ์ ๊ธฐ๋ก ํ, ๋ชจ๋ ์ฐ๊ธฐ๊ฐ ์ฑ๊ณตํด์ผ๋ง ์๋ณธ๊ณผ ๊ต์ฒด๋ฉ๋๋ค.
๋ฐ๋ผ์ ์ค๊ฐ์ ๊บผ์ ธ๋ ๊ธฐ์กด ํ์ผ์ ๋ณด์กด๋๊ณ , ์์๋ ์์ ํ์ผ์ ์๋ ์ ๋ฆฌ๋์ด ์์ ์ฑ์ ํ๋ณดํ ์ ์์ต๋๋ค.
๐ ์๋๋ฆฌ์ค 2: ๋ฉํฐํ๋ก์ธ์ค ํ๊ฒฝ์์ ๊ฒฝ์ ์กฐ๊ฑด(Race Condition)
๋ฌธ์ ์ํฉ:
Python multiprocessing ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์์ง ํ์ดํ๋ผ์ธ์์ ์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ๋์์ ๊ฐ์ ํ์ผ์ ์ ์ฅํ๋ฉฐ ์ถฉ๋์ด ๋ฐ์ํ์ต๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ก๊ทธ ํ์ผ์ด ๋ฎ์ด์ฐ์ฌ ๋๋ฝ๋๊ฑฐ๋, ์ผ๋ถ JSON ํ์ผ์ ํ์ฑํ ์ ์๋ ์์๋ ํํ๋ก ์ ์ฅ๋์ต๋๋ค.
AtomicWriter๋ก ํด๊ฒฐ:
ํ์ผ ์ฐ๊ธฐ๋ฅผ atomic replace ๋ฐฉ์์ผ๋ก ์ํํ๋ฉด, ํ ๋ฒ์ ํ๋์ ํ๋ก์ธ์ค๋ง ์ต์ข
๊ฒฝ๋ก๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์ด๋ก์จ ๊ฒฝ์ ์กฐ๊ฑด ์์ด ์ถฉ๋ ์์ด ์ ์ฅ์ด ๋ณด์ฅ๋ฉ๋๋ค.
๐ ์๋๋ฆฌ์ค 3: ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ๊ฒ์ฆ ๋ถ๊ฐ
๋ฌธ์ ์ํฉ:
ETL ์์
์์ .parquet ์ ์ฅ์ด ์๋ฃ๋๋์ง ์ฌ๋ถ๋ฅผ ์๋ ์์คํ
์ด ํ๋จํ ์ ์์ด, ์์๋๊ฑฐ๋ ๋ฏธ์์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๋จ๊ณ์์ ๊ทธ๋๋ก ์ฌ์ฉํ์ต๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ชจ๋ธ ํ์ต ๋ฐ์ดํฐ์ ๊ฒฐ์ธก๊ฐ์ด ํฌํจ๋์ด ํ์ง ์ ํ๊ฐ ๋ฐ์ํ์ต๋๋ค.
AtomicWriter๋ก ํด๊ฒฐ:
์ ์ฅ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋ ๊ฒฝ์ฐ์๋ง _SUCCESS ํ๋๊ทธ ํ์ผ์ ํจ๊ป ์์ฑํ๋๋ก ์ค์ ํ ์ ์์ต๋๋ค.
ํ์ ๋จ๊ณ๋ _SUCCESS ์ ๋ฌด๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ ํ๊ฒ ํ์ดํ๋ผ์ธ์ ๊ตฌ๋ํ ์ ์์ต๋๋ค.
๐ ์๋๋ฆฌ์ค 4: Polars DataFrame์ S3๋ก ์ ์ฅ ์ค ์ค๋ฅ ๋ฐ์
๋ฌธ์ ์ํฉ:
Polars DataFrame์ AWS S3์ ์ง์ ์ ์ฅํ๋ ์ค๊ฐ์ ConnectionError๊ฐ ๋ฐ์ํ์ฌ S3์๋ ๋ถ๋ถ์ ์ผ๋ก ๊นจ์ง .parquet ํ์ผ์ด ์ฌ๋ผ๊ฐ์ต๋๋ค.
๋ค์ ๋ฒ ์คํ์์ ์ด ํ์ผ์ ์ฌ์ฌ์ฉํ๋ ค ํ์ง๋ง, S3์์ ํ์ผ์ด ์์๋ ์ฑ๋ก ์กด์ฌํด ์ค๋ฅ๋ฅผ ์ ๋ฐํ์ต๋๋ค.
AtomicWriter๋ก ํด๊ฒฐ:
๋ก์ปฌ ์์ ํ์ผ์ ์์ ํ ์ ์ฅ๋ ํ์๋ง S3 ์
๋ก๋ ๋๋ ๊ต์ฒด๊ฐ ์ํ๋ฉ๋๋ค.
๋คํธ์ํฌ ์ด์๋ ๋์คํฌ ์ค๋ฅ์๋ ์ต์ข
ํ์ผ์ ํญ์ ์์ ํ ์ํ๋ก๋ง ์กด์ฌํ๊ฒ ๋ฉ๋๋ค.
Raw data
{
"_id": null,
"home_page": null,
"name": "atio",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "atomic, file, writer, pandas, polars, numpy, data",
"author": null,
"author_email": "Seo Jae Oh <seojaeohcoder@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/ab/09/40c88f1f3ed489fe368d730f8a2e3104e285865c52332c8de7e552077262/atio-1.0.0.tar.gz",
"platform": null,
"description": "# Atio \ud83d\udee1\ufe0f\r\n\r\n\uc548\uc804\ud558\uace0 **\uc6d0\uc790\uc801\uc778 \ud30c\uc77c \uc4f0\uae30**\ub97c \uc9c0\uc6d0\ud558\ub294 \uacbd\ub7c9 Python \ub77c\uc774\ube0c\ub7ec\ub9ac\uc785\ub2c8\ub2e4. \r\nPandas, Polars, NumPy \ub4f1 \ub370\uc774\ud130 \uac1d\uccb4 \uc800\uc7a5 \uc2dc **\ud30c\uc77c \uc190\uc0c1 \uc5c6\uc774**, **\ud2b8\ub79c\uc7ad\uc158\ucc98\ub7fc \uc548\uc804\ud558\uac8c \ucc98\ub9ac**\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\r\n---\r\n\r\n## \ud83c\udf1f \uc8fc\uc694 \uae30\ub2a5\r\n\r\n- \u2705 \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc2a4\ud14c\uc774\uc9d5 \ud6c4 **\uc6d0\uc790\uc801 \ud30c\uc77c \uad50\uccb4** \r\n- \ud83d\udce6 Pandas, Polars, NumPy \ub4f1 \ub2e4\uc591\ud55c \ub370\uc774\ud130 \uac1d\uccb4 \uc9c0\uc6d0 \r\n- \ud83d\udccd `_SUCCESS` \ud50c\ub798\uadf8 \ud30c\uc77c \uc0dd\uc131 \u2014 \uc800\uc7a5 \uc644\ub8cc \uc5ec\ubd80 \ud45c\uc2dc \r\n- \ud83d\udee0 \uc2e4\ud328 \uc2dc **\uc6d0\ubcf8 \ud30c\uc77c \ubcf4\uc874**, \uc784\uc2dc \ud30c\uc77c \uc790\ub3d9 \uc815\ub9ac \r\n- \ud83e\udde9 \ud50c\ub7ec\uadf8\uc778 \uc544\ud0a4\ud14d\ucc98\ub85c **\ud655\uc7a5\uc131 \uc88b\uc74c**\r\n- \ud83d\udd0d **\uc131\ub2a5 \uc9c4\ub2e8 \ub85c\uae45** \u2014 \uac01 \ub2e8\uacc4\ubcc4 \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815 \ubc0f \ubcd1\ubaa9\uc810 \ubd84\uc11d\r\n\r\n---\r\n\r\n## \ud83d\udd0d \uc131\ub2a5 \uc9c4\ub2e8 \ub85c\uae45 (NEW!)\r\n\r\nAtio\ub294 \uc774\uc81c **\uc131\ub2a5 \uc9c4\ub2e8 \ub85c\uae45** \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. `verbose=True` \uc635\uc158\uc744 \uc0ac\uc6a9\ud558\uba74 \uac01 \ub2e8\uacc4\ubcc4 \uc2e4\ud589 \uc2dc\uac04\uc744 \uce21\uc815\ud558\uc5ec \ubcd1\ubaa9\uc810\uc744 \uc815\ud655\ud788 \ud30c\uc545\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\r\n### \uae30\ubcf8 \uc0ac\uc6a9\ubc95 (\uac04\ub2e8\ud55c \uc815\ubcf4\ub9cc):\r\n```python\r\nimport atio as aw\r\nimport pandas as pd\r\n\r\ndf = pd.DataFrame({\"a\": [1, 2, 3]})\r\n\r\n# \uae30\ubcf8 \uc0ac\uc6a9\ubc95 - \uac04\ub2e8\ud55c \uc131\uacf5/\uc2e4\ud328 \uc815\ubcf4\ub9cc\r\naw.write(df, \"output.parquet\", format=\"parquet\")\r\n```\r\n\r\n**\ucd9c\ub825 \uc608\uc2dc:**\r\n```\r\n[INFO] \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc0dd\uc131: /tmp/tmp_xxx\r\n[INFO] \uc784\uc2dc \ud30c\uc77c \uacbd\ub85c: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc0ac\uc6a9\ud560 writer: to_parquet (format: parquet)\r\n[INFO] \ub370\uc774\ud130 \uc784\uc2dc \ud30c\uc77c\uc5d0 \uc800\uc7a5 \uc644\ub8cc: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc6d0\uc790\uc801 \uad50\uccb4 \uc644\ub8cc: /tmp/tmp_xxx/output.parquet -> output.parquet\r\n[INFO] _SUCCESS \ud50c\ub798\uadf8 \ud30c\uc77c \uc0dd\uc131: output.parquet._SUCCESS\r\n[INFO] Atomic write completed successfully (took 0.2359s)\r\n```\r\n\r\n### \uc0c1\uc138 \uc9c4\ub2e8 \ubaa8\ub4dc (verbose=True):\r\n```python\r\n# \uc0c1\uc138\ud55c \uc131\ub2a5 \uc9c4\ub2e8 \uc815\ubcf4 \ucd9c\ub825\r\naw.write(df, \"output.parquet\", format=\"parquet\", verbose=True)\r\n```\r\n\r\n**\ucd9c\ub825 \uc608\uc2dc:**\r\n```\r\n[INFO] \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc0dd\uc131: /tmp/tmp_xxx\r\n[INFO] \uc784\uc2dc \ud30c\uc77c \uacbd\ub85c: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc0ac\uc6a9\ud560 writer: to_parquet (format: parquet)\r\n[INFO] \ub370\uc774\ud130 \uc784\uc2dc \ud30c\uc77c\uc5d0 \uc800\uc7a5 \uc644\ub8cc: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc6d0\uc790\uc801 \uad50\uccb4 \uc644\ub8cc: /tmp/tmp_xxx/output.parquet -> output.parquet\r\n[INFO] _SUCCESS \ud50c\ub798\uadf8 \ud30c\uc77c \uc0dd\uc131: output.parquet._SUCCESS\r\n[DEBUG] Atomic write step timings (SUCCESS): setup=0.0012s, write_call=0.2345s, replace=0.0001s, success_flag=0.0001s, total=0.2359s\r\n```\r\n\r\n### \uc624\ub958 \ubc1c\uc0dd \uc2dc (\uae30\ubcf8 \uc0ac\uc6a9\ubc95):\r\n```\r\n[INFO] \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc0dd\uc131: /tmp/tmp_xxx\r\n[INFO] \uc784\uc2dc \ud30c\uc77c \uacbd\ub85c: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc0ac\uc6a9\ud560 writer: to_parquet (format: parquet)\r\n[ERROR] \uc784\uc2dc \ud30c\uc77c \uc800\uc7a5 \uc911 \uc608\uc678 \ubc1c\uc0dd: [Errno 28] No space left on device\r\n[INFO] Atomic write failed during write stage (took 0.1246s, error: OSError)\r\n```\r\n\r\n### \uc624\ub958 \ubc1c\uc0dd \uc2dc (verbose=True):\r\n```\r\n[INFO] \uc784\uc2dc \ub514\ub809\ud1a0\ub9ac \uc0dd\uc131: /tmp/tmp_xxx\r\n[INFO] \uc784\uc2dc \ud30c\uc77c \uacbd\ub85c: /tmp/tmp_xxx/output.parquet\r\n[INFO] \uc0ac\uc6a9\ud560 writer: to_parquet (format: parquet)\r\n[ERROR] \uc784\uc2dc \ud30c\uc77c \uc800\uc7a5 \uc911 \uc608\uc678 \ubc1c\uc0dd: [Errno 28] No space left on device\r\n[DEBUG] Atomic write step timings (ERROR during write): setup=0.0012s, write_call=0.1234s (\uc2e4\ud328), replace=N/A, success_flag=N/A, total=0.1246s, error_type=OSError\r\n```\r\n\r\n**\uce21\uc815\ub418\ub294 \ub2e8\uacc4:**\r\n- `setup`: \uc784\uc2dc \ud3f4\ub354 \uc0dd\uc131 \ubc0f \ucd08\uae30 \uc124\uc815\r\n- `write_call`: \uc2e4\uc81c \ub370\uc774\ud130 \uc4f0\uae30 \ud568\uc218 \ud638\ucd9c (\ub300\ubd80\ubd84\uc758 \uc2dc\uac04 \uc18c\uc694)\r\n- `replace`: \uc6d0\uc790\uc801 \ud30c\uc77c \uad50\uccb4\r\n- `success_flag`: _SUCCESS \ud50c\ub798\uadf8 \ud30c\uc77c \uc0dd\uc131\r\n- `total`: \uc804\uccb4 \uc791\uc5c5 \uc2dc\uac04\r\n\r\n**\uc9c0\uc6d0\ud558\ub294 \uc624\ub958 \uc0c1\ud669:**\r\n- \u2705 **KeyboardInterrupt**: \uc778\ud130\ub7fd\ud2b8 \ubc1c\uc0dd \uc2dc\uc810\uacfc \uc18c\uc694 \uc2dc\uac04 \ud45c\uc2dc\r\n- \u2705 **\uad8c\ud55c \uc624\ub958**: \ud30c\uc77c \uc2dc\uc2a4\ud15c \uad8c\ud55c \ubb38\uc81c \uc9c4\ub2e8\r\n- \u2705 **\ub514\uc2a4\ud06c \uacf5\uac04 \ubd80\uc871**: \uc800\uc7a5 \uacf5\uac04 \ubd80\uc871 \uc0c1\ud669 \uc9c4\ub2e8\r\n- \u2705 **\uba54\ubaa8\ub9ac \ubd80\uc871**: \uba54\ubaa8\ub9ac \uc555\ubc15 \uc0c1\ud669 \uc9c4\ub2e8\r\n- \u2705 **\ub124\ud2b8\uc6cc\ud06c \uc624\ub958**: \ub124\ud2b8\uc6cc\ud06c \ub4dc\ub77c\uc774\ube0c \uc811\uadfc \ubb38\uc81c \uc9c4\ub2e8\r\n- \u2705 **\uc9c0\uc6d0\ud558\uc9c0 \uc54a\ub294 \ud615\uc2dd**: \uc798\ubabb\ub41c \ud30c\uc77c \ud615\uc2dd \uc9c0\uc815 \uc2dc \uc9c4\ub2e8\r\n- \u2705 **\ub3d9\uc2dc \uc811\uadfc \uc624\ub958**: \uba40\ud2f0\uc2a4\ub808\ub529 \ud658\uacbd\uc5d0\uc11c\uc758 \ucda9\ub3cc \uc9c4\ub2e8\r\n\r\n**\uc7a5\uc810:**\r\n- \ud83c\udfaf **\uc815\ud655\ud55c \ubcd1\ubaa9\uc810 \ud30c\uc545**: Atio \uc624\ubc84\ud5e4\ub4dc vs \uc2e4\uc81c \uc4f0\uae30 \uc791\uc5c5 \uc2dc\uac04 \uad6c\ubd84\r\n- \ud83d\udd27 **\uc131\ub2a5 \ucd5c\uc801\ud654 \uac00\uc774\ub4dc**: \uc5b4\ub290 \ub2e8\uacc4\uc5d0\uc11c \uc2dc\uac04\uc774 \ub9ce\uc774 \uc18c\uc694\ub418\ub294\uc9c0 \uba85\ud655\ud788 \ud45c\uc2dc\r\n- \ud83d\udc1b **\ub514\ubc84\uae45 \uc2dc\uac04 \ub2e8\ucd95**: \ubb38\uc81c\uc758 \uc6d0\uc778\uc744 \ube60\ub974\uac8c \ud30c\uc545 \uac00\ub2a5\r\n- \ud83d\udcca **\uc131\ub2a5 \ubaa8\ub2c8\ud130\ub9c1**: \ub300\uc6a9\ub7c9 \ub370\uc774\ud130 \ucc98\ub9ac \uc2dc \uc131\ub2a5 \ucd94\uc801\r\n- \ud83d\udea8 **\uc624\ub958 \uc9c4\ub2e8**: \uc2e4\ud328 \uc0c1\ud669\uc5d0\uc11c\ub3c4 \uc815\ud655\ud55c \uc6d0\uc778\uacfc \ubc1c\uc0dd \uc2dc\uc810 \ud30c\uc545\r\n\r\n---\r\n\r\n## \ud83e\udde0 \uc65c \uc774 \ub3c4\uad6c\uac00 \uc815\ub9d0 \uc911\uc694\ud55c\uac00\uc694?\r\n\r\nNumPy\ub098 Pandas\ub294 \ub370\uc774\ud130 \ubd84\uc11d\uc5d0\uc11c\ub294 \ucd5c\uc801\uc774\uc9c0\ub9cc, **\ud30c\uc77c\ub85c \uc800\uc7a5\ud560 \ub54c\ub294 \uc544\ub798\uc640 \uac19\uc740 \uc704\ud5d8**\uc774 \uc788\uc2b5\ub2c8\ub2e4:\r\n\r\n1. **\ud30c\uc77c \uc77c\ubd80\ub9cc \uc800\uc7a5\ub418\uc5b4 \uae68\uc9c8 \uc218 \uc788\uc74c** \u2014 \uac15\uc81c \uc885\ub8cc\ub098 \uc624\ub958 \uc2dc\r\n2. **\ub3d9\uc2dc \uc4f0\uae30 \ucda9\ub3cc** \u2014 \uba40\ud2f0\ud504\ub85c\uc138\uc2a4 \ud658\uacbd\uc5d0\uc11c \ud30c\uc77c\uc774 \uc5c9\ud0ac \uc218 \uc788\uc74c\r\n3. **\ud50c\ub7ab\ud3fc \uac04 \ub3d9\uc791 \ucc28\uc774** \u2014 Windows\uc640 Linux/macOS\uc5d0\uc11c \ud30c\uc77c \uc2dc\uc2a4\ud15c \ub3d9\uc791\uc774 \ub2e4\ub984\r\n\r\nAtomicWriter\ub294 \uc784\uc2dc \ud30c\uc77c\uc5d0 \uc4f0\uace0 **\ub2e8\uc77c `rename()`/`replace()` \uc791\uc5c5\uc73c\ub85c \uad50\uccb4**\ud569\ub2c8\ub2e4. \r\n\uc774 \ubc29\uc2dd\uc740 **\u201c\uc644\uc804\ud788 \uc800\uc7a5\ub418\uac70\ub098 \uc804\ud600 \uc800\uc7a5\ub418\uc9c0 \uc54a\ub294\u201d** \uc6d0\uc790\uc131(atomicity)\uc744 \ubcf4\uc7a5\ud558\uba70, \r\n- POSIX: `os.replace` (atomic), `fsync` \r\n- Windows: `MoveFileEx`, `Commit` \r\n\ub97c \ud65c\uc6a9\ud558\uc5ec \ud30c\uc77c\uc774 **\ud56d\uc0c1 \uc77c\uad00\ub41c \uc0c1\ud0dc**\ub97c \uc720\uc9c0\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4 :contentReference[oaicite:1]{index=1}.\r\n\r\n---\r\n\r\n## \u2699\ufe0f \uc124\uce58\r\n\r\n```bash\r\npip install atomicwriter\r\n\r\n## \ud83d\udee0\ufe0f \uc0ac\uc6a9 \uc608\uc81c\r\n\r\n```python\r\nimport atomicwriter as aw\r\nimport pandas as pd\r\n\r\ndf = pd.DataFrame({\"a\": [1, 2, 3]})\r\n\r\n# \uae30\ubcf8 \uc0ac\uc6a9\ubc95\r\naw.write(df, \"output.parquet\", format=\"parquet\")\r\n# \u2502\u2192 \uc784\uc2dc \ud30c\uc77c \uc791\uc131 \u2192 \uc6d0\uc790\uc801 \uad50\uccb4 \u2192 _SUCCESS \uc0dd\uc131\r\n# \u2502\u2192 \uc2e4\ud328 \uc2dc \uc6d0\ubcf8 \ubcf4\uc874, \uc784\uc2dc \ud30c\uc77c \uc790\ub3d9 \uc815\ub9ac\r\n\r\n# \uc0c1\uc138 \uc131\ub2a5 \uc9c4\ub2e8 \ub85c\uae45 \ud65c\uc131\ud654\r\naw.write(df, \"output_verbose.parquet\", format=\"parquet\", verbose=True)\r\n# \u2502\u2192 \uac01 \ub2e8\uacc4\ubcc4 \uc2e4\ud589 \uc2dc\uac04 \uce21\uc815 \ubc0f \ub85c\uadf8 \ucd9c\ub825\r\n\r\n# \uc9c4\ud589\ub3c4 \ud45c\uc2dc\uc640 \ud568\uaed8 \uc0ac\uc6a9\r\naw.write(df, \"output_progress.parquet\", format=\"parquet\", show_progress=True)\r\n# \u2502\u2192 \uc2e4\uc2dc\uac04 \uc9c4\ud589\ub3c4 \ud45c\uc2dc\r\n\r\n# \ubaa8\ub4e0 \uc635\uc158 \uc870\ud569\r\naw.write(df, \"output_full.parquet\", format=\"parquet\", \r\n verbose=True, show_progress=True)\r\n# \u2502\u2192 \uc131\ub2a5 \uc9c4\ub2e8 + \uc9c4\ud589\ub3c4 \ud45c\uc2dc\r\n```\r\n\r\n## \ud83d\udca1 \ube45\ub370\uc774\ud130 \uc6cc\ud06c\ud50c\ub85c\uc6b0\uc5d0\uc11c \ud65c\uc6a9 \uc2dc\ub098\ub9ac\uc624\r\n\r\n| \uc2dc\ub098\ub9ac\uc624 | \ud574\uacb0 \ubc29\ubc95 | \uc7a5\uc810 |\r\n|------------------------|-----------------------------|-------------------------|\r\n| Pandas \u2192 CSV \uc800\uc7a5 | \uc784\uc2dc \ud30c\uc77c\uc5d0 \uae30\ub85d \ud6c4 \uad50\uccb4 | CSV \ud30c\uc77c \uae68\uc9d0 \ubc29\uc9c0 |\r\n| \uba40\ud2f0\ud504\ub85c\uc138\uc2a4 \ubcd1\ub82c \uc4f0\uae30 | atomic replace \ubc29\uc2dd \uc0ac\uc6a9 | \ucda9\ub3cc \uc5c6\ub294 \uc548\uc804 \uc800\uc7a5 |\r\n| \ub370\uc774\ud130 \ud30c\uc774\ud504\ub77c\uc778 \uc791\uc5c5 | \uc800\uc7a5 \uc131\uacf5 \uc2dc `_SUCCESS` \ud655\uc778 | \ub370\uc774\ud130 \uc644\uc804\uc131 \ubcf4\uc7a5 |\r\n\r\n---\r\n\r\n## \ud83d\udd04 \ube44\uad50 \u2013 \uc720\uc0ac \ub77c\uc774\ube0c\ub7ec\ub9ac \ud2b9\uc9d5 \uc815\ub9ac\r\n\r\n### [python-atomicwrites](https://github.com/untitaker/python-atomicwrites)\r\n- \uac04\ud3b8\ud55c API\r\n- Windows \uc9c0\uc6d0\r\n- \ud06c\ub85c\uc2a4 \ud50c\ub7ab\ud3fc \ud638\ud658\r\n\r\n### atomicwriter (\ubcf8 \ud504\ub85c\uc81d\ud2b8)\r\n- \u2705 \uacbd\ub7c9\r\n- \u2705 \ud50c\ub7ec\uadf8\uc778 \uc544\ud0a4\ud14d\ucc98\r\n- \u2705 Pandas / Polars / Numpy \ub4f1 \ub370\uc774\ud130 \uac1d\uccb4 \uc911\uc2ec \uc800\uc7a5 \uc9c0\uc6d0\r\n\r\n---\r\n\r\n## \u2705 \ub77c\uc774\uc120\uc2a4\r\n\r\nApache 2.0 \u2014 \uae30\uc5c5 \ubc0f \ucee4\ubba4\ub2c8\ud2f0 \ubaa8\ub450 \uc790\uc720\ub86d\uac8c \uc0ac\uc6a9 \uac00\ub2a5\r\n\r\n---\r\n\r\n## \u2728 \uc694\uc57d\r\n\r\n**AtomicWriter**\ub294 \ubd84\uc11d\ub9cc\ud07c \uc911\uc694\ud55c **\u201c\uc800\uc7a5\u201d \ub2e8\uacc4\ub97c \uc548\uc804\ud558\uac8c \ucc98\ub9ac**\ud558\ub294 \ub3c4\uad6c\uc785\ub2c8\ub2e4.\r\n\r\n\ud2b9\ud788 \ub370\uc774\ud130 \ubb34\uacb0\uc131\uc774 \uc911\uc694\ud55c \ud658\uacbd\uc5d0\uc11c \r\n(\uc608: \uba38\uc2e0\ub7ec\ub2dd \ubc30\uce58, \uba40\ud2f0\ud504\ub85c\uc138\uc2a4 \ubd84\uc11d, \uc911\uc694 \ub85c\uadf8 \uc800\uc7a5 \ub4f1) \r\n**\uc791\uc9c0\ub9cc \uac15\ub825\ud55c \ud574\uacb0\ucc45**\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.\r\n\r\n\ud83d\udcd8 \uc2dc\ub098\ub9ac\uc624 1: Pandas CSV \uc800\uc7a5 \uc911 \uc791\uc5c5 \uc911\ub2e8\r\n\ubb38\uc81c \uc0c1\ud669:\r\n\ud55c \uc0ac\uc6a9\uc790\uac00 Pandas\ub85c \ub300\uc6a9\ub7c9 \ubd84\uc11d \uacb0\uacfc\ub97c .csv \ud30c\uc77c\ub85c \uc800\uc7a5\ud558\ub358 \uc911, \uc608\uc0c1\uce58 \ubabb\ud55c \uc804\uc6d0 \ucc28\ub2e8\uc774\ub098 \ucee4\ub110 \uac15\uc81c \uc885\ub8cc\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\r\n\uacb0\uacfc \ud30c\uc77c\uc740 50MB \uc911 3MB\ub9cc \uc800\uc7a5\ub41c \ucc44 \uc190\uc0c1\ub418\uc5c8\uace0, \uc774\ud6c4 \uc77d\uae30\ub3c4 \ub418\uc9c0 \uc54a\uc558\uc2b5\ub2c8\ub2e4.\r\n\r\nAtomicWriter\ub85c \ud574\uacb0:\r\n\uc784\uc2dc \ud30c\uc77c\uc5d0 \uba3c\uc800 \uae30\ub85d \ud6c4, \ubaa8\ub4e0 \uc4f0\uae30\uac00 \uc131\uacf5\ud574\uc57c\ub9cc \uc6d0\ubcf8\uacfc \uad50\uccb4\ub429\ub2c8\ub2e4.\r\n\ub530\ub77c\uc11c \uc911\uac04\uc5d0 \uaebc\uc838\ub3c4 \uae30\uc874 \ud30c\uc77c\uc740 \ubcf4\uc874\ub418\uace0, \uc190\uc0c1\ub41c \uc784\uc2dc \ud30c\uc77c\uc740 \uc790\ub3d9 \uc815\ub9ac\ub418\uc5b4 \uc548\uc815\uc131\uc744 \ud655\ubcf4\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\r\n\ud83d\udcd8 \uc2dc\ub098\ub9ac\uc624 2: \uba40\ud2f0\ud504\ub85c\uc138\uc2a4 \ud658\uacbd\uc5d0\uc11c \uacbd\uc7c1 \uc870\uac74(Race Condition)\r\n\ubb38\uc81c \uc0c1\ud669:\r\nPython multiprocessing \uae30\ubc18 \ub370\uc774\ud130 \uc218\uc9d1 \ud30c\uc774\ud504\ub77c\uc778\uc5d0\uc11c \uc5ec\ub7ec \ud504\ub85c\uc138\uc2a4\uac00 \ub3d9\uc2dc\uc5d0 \uac19\uc740 \ud30c\uc77c\uc744 \uc800\uc7a5\ud558\uba70 \ucda9\ub3cc\uc774 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\r\n\uacb0\uacfc\uc801\uc73c\ub85c \ub85c\uadf8 \ud30c\uc77c\uc774 \ub36e\uc5b4\uc4f0\uc5ec \ub204\ub77d\ub418\uac70\ub098, \uc77c\ubd80 JSON \ud30c\uc77c\uc740 \ud30c\uc2f1\ud560 \uc218 \uc5c6\ub294 \uc190\uc0c1\ub41c \ud615\ud0dc\ub85c \uc800\uc7a5\ub410\uc2b5\ub2c8\ub2e4.\r\n\r\nAtomicWriter\ub85c \ud574\uacb0:\r\n\ud30c\uc77c \uc4f0\uae30\ub97c atomic replace \ubc29\uc2dd\uc73c\ub85c \uc218\ud589\ud558\uba74, \ud55c \ubc88\uc5d0 \ud558\ub098\uc758 \ud504\ub85c\uc138\uc2a4\ub9cc \ucd5c\uc885 \uacbd\ub85c\ub85c \uc774\ub3d9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\uc774\ub85c\uc368 \uacbd\uc7c1 \uc870\uac74 \uc5c6\uc774 \ucda9\ub3cc \uc5c6\uc774 \uc800\uc7a5\uc774 \ubcf4\uc7a5\ub429\ub2c8\ub2e4.\r\n\r\n\ud83d\udcd8 \uc2dc\ub098\ub9ac\uc624 3: \ub370\uc774\ud130 \ud30c\uc774\ud504\ub77c\uc778 \uac80\uc99d \ubd88\uac00\r\n\ubb38\uc81c \uc0c1\ud669:\r\nETL \uc791\uc5c5\uc5d0\uc11c .parquet \uc800\uc7a5\uc774 \uc644\ub8cc\ub410\ub294\uc9c0 \uc5ec\ubd80\ub97c \uc790\ub3d9 \uc2dc\uc2a4\ud15c\uc774 \ud310\ub2e8\ud560 \uc218 \uc5c6\uc5b4, \uc190\uc0c1\ub418\uac70\ub098 \ubbf8\uc644\uc131\ub41c \ub370\uc774\ud130\ub97c \ub2e4\uc74c \ub2e8\uacc4\uc5d0\uc11c \uadf8\ub300\ub85c \uc0ac\uc6a9\ud588\uc2b5\ub2c8\ub2e4.\r\n\uacb0\uacfc\uc801\uc73c\ub85c \ubaa8\ub378 \ud559\uc2b5 \ub370\uc774\ud130\uc5d0 \uacb0\uce21\uac12\uc774 \ud3ec\ud568\ub418\uc5b4 \ud488\uc9c8 \uc800\ud558\uac00 \ubc1c\uc0dd\ud588\uc2b5\ub2c8\ub2e4.\r\n\r\nAtomicWriter\ub85c \ud574\uacb0:\r\n\uc800\uc7a5\uc774 \uc131\uacf5\uc801\uc73c\ub85c \uc644\ub8cc\ub41c \uacbd\uc6b0\uc5d0\ub9cc _SUCCESS \ud50c\ub798\uadf8 \ud30c\uc77c\uc744 \ud568\uaed8 \uc0dd\uc131\ud558\ub3c4\ub85d \uc124\uc815\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\ud6c4\uc18d \ub2e8\uacc4\ub294 _SUCCESS \uc720\ubb34\ub97c \uae30\uc900\uc73c\ub85c \uc548\uc804\ud558\uac8c \ud30c\uc774\ud504\ub77c\uc778\uc744 \uad6c\ub3d9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\r\n\r\n\ud83d\udcd8 \uc2dc\ub098\ub9ac\uc624 4: Polars DataFrame\uc744 S3\ub85c \uc800\uc7a5 \uc911 \uc624\ub958 \ubc1c\uc0dd\r\n\ubb38\uc81c \uc0c1\ud669:\r\nPolars DataFrame\uc744 AWS S3\uc5d0 \uc9c1\uc811 \uc800\uc7a5\ud558\ub294 \uc911\uac04\uc5d0 ConnectionError\uac00 \ubc1c\uc0dd\ud558\uc5ec S3\uc5d0\ub294 \ubd80\ubd84\uc801\uc73c\ub85c \uae68\uc9c4 .parquet \ud30c\uc77c\uc774 \uc62c\ub77c\uac14\uc2b5\ub2c8\ub2e4.\r\n\ub2e4\uc74c \ubc88 \uc2e4\ud589\uc5d0\uc11c \uc774 \ud30c\uc77c\uc744 \uc7ac\uc0ac\uc6a9\ud558\ub824 \ud588\uc9c0\ub9cc, S3\uc5d0\uc11c \ud30c\uc77c\uc774 \uc190\uc0c1\ub41c \ucc44\ub85c \uc874\uc7ac\ud574 \uc624\ub958\ub97c \uc720\ubc1c\ud588\uc2b5\ub2c8\ub2e4.\r\n\r\nAtomicWriter\ub85c \ud574\uacb0:\r\n\ub85c\uceec \uc784\uc2dc \ud30c\uc77c\uc5d0 \uc644\uc804\ud788 \uc800\uc7a5\ub41c \ud6c4\uc5d0\ub9cc S3 \uc5c5\ub85c\ub4dc \ub610\ub294 \uad50\uccb4\uac00 \uc218\ud589\ub429\ub2c8\ub2e4.\r\n\ub124\ud2b8\uc6cc\ud06c \uc774\uc288\ub098 \ub514\uc2a4\ud06c \uc624\ub958\uc5d0\ub3c4 \ucd5c\uc885 \ud30c\uc77c\uc740 \ud56d\uc0c1 \uc644\uc804\ud55c \uc0c1\ud0dc\ub85c\ub9cc \uc874\uc7ac\ud558\uac8c \ub429\ub2c8\ub2e4.\r\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Safe atomic file writer for Pandas, Polars, NumPy, and other data objects",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/seojaeohcode/atomic-writer"
},
"split_keywords": [
"atomic",
" file",
" writer",
" pandas",
" polars",
" numpy",
" data"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "1f719d6d8dcbdbd33c177f04da9065122ef220ac799bb01f0977d580bb7d442e",
"md5": "8977d01e75b0e81a1bead503724ffee9",
"sha256": "78987d8959eda0c467401a0635d9c76bfa5407d3423c94633f197c974553755f"
},
"downloads": -1,
"filename": "atio-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8977d01e75b0e81a1bead503724ffee9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 23193,
"upload_time": "2025-08-02T08:57:22",
"upload_time_iso_8601": "2025-08-02T08:57:22.429264Z",
"url": "https://files.pythonhosted.org/packages/1f/71/9d6d8dcbdbd33c177f04da9065122ef220ac799bb01f0977d580bb7d442e/atio-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ab0940c88f1f3ed489fe368d730f8a2e3104e285865c52332c8de7e552077262",
"md5": "6432ddcb8e5a9df4b09eaf4a2fa426fa",
"sha256": "7f1500863affcfd2dbcb412e47a0b9f771ffea0629bf59e68cfd1cbd4b262e41"
},
"downloads": -1,
"filename": "atio-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "6432ddcb8e5a9df4b09eaf4a2fa426fa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 32295,
"upload_time": "2025-08-02T08:57:23",
"upload_time_iso_8601": "2025-08-02T08:57:23.908860Z",
"url": "https://files.pythonhosted.org/packages/ab/09/40c88f1f3ed489fe368d730f8a2e3104e285865c52332c8de7e552077262/atio-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-02 08:57:23",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "seojaeohcode",
"github_project": "atomic-writer",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "pandas",
"specs": []
},
{
"name": "pyarrow",
"specs": []
},
{
"name": "polars",
"specs": []
},
{
"name": "pytest",
"specs": []
},
{
"name": "build",
"specs": []
},
{
"name": "twine",
"specs": []
}
],
"lcname": "atio"
}