Как исправить ошибку торнадо с помощью «Попытка записи x байтов меньше, чем Content-Length» в Python - PullRequest
1 голос
/ 30 апреля 2019

Я пытаюсь создать свой собственный обработчик в торнадо, который наследуется от StaticFileHandler, который архивирует определенные файлы в каталоге.Вот код:

import tempfile
import zipfile

from tornado.web import (
    StaticFileHandler,
)
from tornado import gen

class ZipDirHandler(StaticFileHandler):
    def initialize(self, path):
        self.root = tempfile.gettempdir()
        self.root_zip = path
        self.default_filename = None

    @gen.coroutine
    def get(self, path, include_body=True):
        self.path = self.parse_url_path(path)
        del path  # make sure we don't refer to path instead of self.path again
        self.absolute_path = self.get_absolute_path(self.root_zip, self.path)
        zipf = self.zipdir(self.absolute_path)  # Create zip file
        super(ZipDirHandler,self).get(zipf)
        os.remove(zipf)

    def zipdir(self, path):
        zip_fd, zip_name = tempfile.mkstemp()
        ziph = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
        for file_name in os.listdir(path):
            abs_path = os.path.join(path, file_name)
            if (os.path.isfile(abs_path) and
                file_name.lower().endswith(('.txt','.py', '.xml'))):
                ziph.write(abs_path)
        ziph.close()
        os.close(zip_fd)
        return zip_name

К сожалению, он не работает, пока я пытался загрузить каталог, содержащий 25 тыс. Файлов TXT, которые у меня есть (с помощью wget):

Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:45678... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:45678... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5616592 (5.4M) [application/octet-stream]
Saving to: ‘many.11’

many.11                         2%[>                                                ] 128.00K  --.-KB/s    in 0s      

2019-04-30 14:26:23 (863 MB/s) - Connection closed at byte 131072. Retrying.

--2019-04-30 14:26:24--  (try: 2)  http://localhost:45678/files/many
Connecting to localhost (localhost)|127.0.0.1|:45678... connected.
HTTP request sent, awaiting response... 206 Partial Content
Length: 5616592 (5.4M), 5485520 (5.2M) remaining [application/octet-stream]
Saving to: ‘many.11’

many.11                         4%[+>                                               ] 256.00K  --.-KB/s    in 0s      

2019-04-30 14:26:26 (960 MB/s) - Connection closed at byte 262144. Retrying.

--2019-04-30 14:26:28--  (try: 3)  http://localhost:45678/files/many
Connecting to localhost (localhost)|127.0.0.1|:45678... connected.
HTTP request sent, awaiting response... ^C

Иэто идет, пока это не загружает полный файл.

На торнадо в журналах я вижу:

HTTPServerRequest(protocol='http', host='localhost:45678', method='GET', uri='/files/many', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/web.py", line 1594, in _execute
    self.finish()
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/web.py", line 1053, in finish
    self.request.connection.finish()
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/http1connection.py", line 463, in finish
    self._expected_content_remaining)
tornado.httputil.HTTPOutputError: Tried to write 5485520 bytes less than Content-Length
2019-04-30 14:26:23,261 - MainThread - send_error - ERROR - Cannot send error response after headers written
2019-04-30 14:26:26,435 - MainThread - log_exception - ERROR - Uncaught exception GET /files/many (127.0.0.1)
HTTPServerRequest(protocol='http', host='localhost:45678', method='GET', uri='/files/many', version='HTTP/1.1', remote_ip='127.0.0.1')
Traceback (most recent call last):
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/web.py", line 1594, in _execute
    self.finish()
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/web.py", line 1053, in finish
    self.request.connection.finish()
  File "/home/cwiklins/Worke/SCMINFRA-787/venv/lib/python3.7/site-packages/tornado/http1connection.py", line 463, in finish
    self._expected_content_remaining)
tornado.httputil.HTTPOutputError: Tried to write 5354448 bytes less than Content-Length
2019-04-30 14:26:26,435 - MainThread - send_error - ERROR - Cannot send error response after headers written

Основная проблема в том, что соединение закрыто, так как wget может повторить попытку загрузки, но другие компоненты, использующие эту конечную точку, не могут его загрузить,Даже Firefox говорит, что tmp/PN2DwL2H.part could not be saved, because the source file could not be read.

Не могли бы вы сказать мне, что не так?Или где мне искать проблему?Я подозреваю, что с моей реализацией наследования что-то не так.

Я протестировал это с несколькими версиями Python, такими как 3.6, 3.7, а в tornado lib установлено 5.1.1.

...