Кажется, день, оставшийся до этой проблемы, прояснил мое понимание проблемы. Я объясню свое мышление и то, что я нашел.
tldr Я перепутал tarinfo, tarfile и exfileobjects.
Согласно OP файлы, переданные в open()
, под обложками представлены как <_io.BufferedReader name='myfile.tar.xz'>
. Таким образом, получение кода для работы с незашифрованным файлом и open()
на самом деле только доказывает, что файл не был поврежден. Так что никаких проблем, я не буду повторять это снова.
Следуя примеру кода в OP, вызов decrypted_data.data
возвращает необработанную байтовую строку из объекта decrypted_data
. Эти необработанные байты - мои 2 файла tar. Несжатый tar и вложенная структура сжатого tar. Строка начинается с b'myfile.tar.xz\x00\x00\x00\......
et c. Мы оборачиваем это нас как байтовый объект io.BytesIO(decrypted_data.data)
, чтобы у нас был интерфейс для работы, и чтобы его можно было передать в tarfile.open()
изначально. Пока все хорошо, но тут все начало go неправильно.
Я решил go с двумя менеджерами контекста в следующем коде. В OP я дважды звонил по номеру tarfile.open()
, наверное, я предполагал, что была операция извлечения вместе с mode='r'
. Вы можете видеть, что теперь я делаю 2 вызова extractfile()
на member
каждого диспетчера контекста. Первый extractfile()
извлекает tar.xz из несжатого tar. Это «файл» ExFileObject
, который я в конечном итоге передаю следующему диспетчеру контекста как mode=r:xz
. В OP это был бы объект TarInfo
, а не извлеченные данные, что неверно.
Второй вызов extractfile()
выполняется на member
второго диспетчера контекста, чтобы получить readable_members_value
от myfile.tar.xz
.
with tarfile.open(fileobj=io_bytes_file_like_object, mode='r') as uncompressed_tar_file:
# uncompressed_tar_file is tarfile.TarFile object
for member in uncompressed_tar_file.getmembers():
# member is TarInfo object
tar_file_object = uncompressed_tar_file.extractfile(member)
# tar_file_object is ExFileObject
with tarfile.open(fileobj=tar_file_object, mode='r:xz', debug=3, errorlevel=2) as lzma_compressed_tar_file:
for member in lzma_compressed_tar_file.getmembers():
if member.isfile():
readable_members_value = lzma_compressed_tar_file.extractfile(member)
# now works where it failed before equivalent to something like file_o.read() in OP
print(readable_members_value.read())
decoded_readable_member_value = readable_member_value.read().decode("utf-8")
json_data = json.loads(decoded_readable_member_value)
print(json_data)
Остальная часть кода практически идентичен, за исключением последних нескольких строк. Вы можете видеть по именам переменных в OP, я ожидал, что file_o
будет файловым объектом. json.load(file_o)
будет работать с указателем файла, но в этом случае readable_member.read()
возвращает литерал байтов b''
, поэтому на самом деле json.loads()
мне не нужно json.load()
.