Потоковые потоки Python `TarFile` и` os.pipe () `: архив не завершен - PullRequest
0 голосов
/ 08 ноября 2019

Я пытаюсь создать tar архив в Python и во время создания отправлять / передавать свои байты на удаленный хост. Связь с удаленным хостом осуществляется по специальному протоколу, в котором каждое сообщение / пакет несет полезную нагрузку определенного размера.

Чтобы попробовать параллельное создание и чтение архива tar, я написал следующий простой тестовый скрипт:

import tarfile
import threading
import os
import select

BLOCKSIZE = 4096

(r,w) = os.pipe()
wfd = os.fdopen(w, "w")

def maketar(buf, paths):
    tar = tarfile.open(mode='w|', fileobj=buf)
    for p in paths:
        tar.add(p)
    tar.close()

x = threading.Thread(target=maketar, args=(wfd, ["1M", "2M"]))
x.start()

poller = select.poll()
poller.register(r, select.POLLIN)

with open("out/archive.tar", "wb") as outf:
    while True:
        if poller.poll(10):
            outf.write(os.read(r, BLOCKSIZE))
        elif not x.is_alive():
            break

Файлы 1M и 2M должны быть упакованы в out/archive.tar. Однако архив будет поврежден после завершения работы скрипта:

$ tar xf archive.tar
tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
$ ls -la
total 4.0M
-rw-rw-r-- 1 xx xx  1.0M Nov  8 11:37 1M
-rw-rw-r-- 1 xx xx 1023K Nov  8 13:12 2M
-rw-rw-r-- 1 xx xx  2.0M Nov  8 12:55 archive.tar

Оба файла должны иметь размер 1M;размер архива приблизительно правильный, но 2M слишком мал. Что мне здесь не хватает? Это проблема буферизации файловых дескрипторов os.pipe()?

1 Ответ

1 голос
/ 08 ноября 2019

Оказывается, мне просто нужно buf.flush() буфер записи в конце функции maketar(). Теперь работает нормально.

def maketar(buf, paths):
    tar = tarfile.open(mode='w|', fileobj=buf)
    for p in paths:
        tar.add(p)
    tar.close()
    buf.flush()
...