я сделал простой код запроса, который загружает файл с сервера
r = requests.get("https:.../index_en.txt.lzma")
index_en= open('C:\...\index_en.txt.lzma','wb')
index_en.write(r.content)
index_en.close
когда я сейчас извлекаю файл вручную в каталог с помощью 7zip, все в порядке, и файл расшифровывается как обычно.
Я попробовал два способа сделать это в программе ython, но поскольку файл заканчивается на .lzma, я думаю, что следующий подход является лучшим.
import lzma
with open('C:\...\index_en.txt.lzma') as compressed:
print(compressed.readline)
with lzma.LZMAFile(compressed) as uncompressed:
for line in uncompressed:
print(line)
этот дает мне ошибку: «Сжатый файл закончился до того, как был достигнут маркер конца потока» в строке с циклом for.
второй способ, который я пробовал, был с 7zip, потому что вручную он работал нормально
with py7zr.SevenZipFile("C:\...\index_en.txt.lzma", 'w') as archive:
archive.extract(path = "C:\...\Json")
этот дает мне ошибку: OSError 22 Invalid Argument в строке "with py7zr..."
я действительно не понимаю, где проблема здесь. ПОЧЕМУ это работает вручную, но не в питоне? Спасибо






Вы не закрыли свой файл, поэтому данные, застрявшие в буферах пользовательского режима, не видны на диске до тех пор, пока файл не будет очищен в какой-то неопределенный момент в будущем (может не произойти вообще, а может и не произойти, пока программа не завершит работу, даже если она делает). Из-за этого любая попытка доступа к файлу любым способом, кроме единственного дескриптора, который вы написали, не увидит несброшенные данные, что приведет к тому, что он будет выглядеть так, как будто файл был усечен, что приведет к ошибке, которую вы наблюдаете.
Минимальное решение — вызвать close, заменив index_en.close на index_en.close(). Но на практике вы должны использовать операторы with для всех файлов (и замков, и сокетов, и всех других ресурсов, требующих очистки), когда это возможно, поэтому даже при возникновении исключения файл обязательно закрывается; это наиболее важно для файлов, в которые вы записываете (где данные могут не сбрасываться на диск без него), но даже для файлов, открытых для чтения, в патологических случаях вы можете в конечном итоге достичь предела дескриптора открытого файла.
Переписав свой первый блок кода, чтобы сделать его полностью безопасным, вы получите:
with requests.get("https:.../index_en.txt.lzma") as r, open(r'C:\...\index_en.txt.lzma','wb') as index_en:
index_en.write(r.content)
Примечание. Объекты request.Response также являются диспетчерами контекста, поэтому я добавил их в with, чтобы гарантировать, что базовое соединение будет быстро возвращено в пул. Я также добавил к вашему локальному пути префикс r, чтобы сделать его необработанной строкой; в Windows, с обратной косой чертой в пути, вы всегда хотите сделать это, чтобы файл или каталог, начинающийся с символа, который Python распознает как escape-литерал строки, не был поврежден (например, "C:\foo" на самом деле "C:<form feed>oo", не содержащий обратной косой черты ни f).
Вы даже можете немного оптимизировать его, если файл большой, путем потоковой передачи данных в файл (требуется в основном фиксированная нагрузка на память, привязанная к размеру буфера базового соединения), а не жадная выборка (требуется память, пропорциональная размеру файла). ):
# stream=True means underlying file is opened without being immediately
# read into memory
with requests.get("https:.../index_en.txt.lzma", stream=True) as r, open(r'C:\...\index_en.txt.lzma','wb') as index_en:
# iter_content(None) produces an iterator of chunks of data (of whatever size
# is available in a single system call)
# Changing to writelines means the iterator is consumed and written
# as the data arrives
index_en.writelines(r.iter_content(None))
Управление requests.get с помощью оператора with здесь более важно (поскольку режим stream=True означает, что базовый сокет не потребляется и не освобождается немедленно).
Также обратите внимание, что print(compressed.readline) ничего не делает (потому что вы не звонили readline). Если в ответе перед необработанными данными LZMA есть какая-то строка текста, вы не смогли ее пропустить. Если бы такой мусорной строки не было, и если бы вы правильно вызвали readline (с print(compressed.readline())), это нарушило бы декомпрессию, потому что указатель файла теперь пропустил бы первые несколько (или много) байтов файла, приземлившись на какой-то в основном случайное смещение.
Наконец,
with py7zr.SevenZipFile("C:\...\index_en.txt.lzma", 'w') as archive:
archive.extract(path = "C:\...\Json")
неверно, потому что вы передали ему режим, указывающий, что вы открываете его для записи, когда вы явно пытаетесь его прочитать; либо опустите 'w', либо замените его на 'r'.
index_en.closeне имеет никакого эффекта, вы должны вызвать функцию:index_en.close(), но предпочтительнее использовать контекстные менеджеры (with).print(compressed.readline)неверно по той же причине, это просто печатает описание метода. Строкаwithневерна, так как вы забыли экранировать обратную косую черту и использовали неправильный режим (wвместоr). Может быть, немного больше исследований не повредит. Чтобы этот вопрос был актуален в Stack Overflow, сосредоточьтесь одновременно на одной проблеме и создайте минимально воспроизводимый пример.