Werkzeug: Python3-Kompatibilitätsproblem in get_content_type()

Erstellt am 4. Dez. 2014  ·  10Kommentare  ·  Quelle: pallets/werkzeug

Ich verwende Django mit django_extensions , das werkzeug zum Debuggen verwendet, wenn runserver_plus . Werkzeug scheint in get_content_type() mit folgendem Traceback zu explodieren, wenn Python3 verwendet wird:

Traceback (most recent call last):
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py", line 177, in run_wsgi
    execute(self.server.app)
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py", line 165, in execute
    application_iter = app(environ, start_response)
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py", line 173, in __call__
    response = self.get_resource(request, arg)
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py", line 154, in get_resource
    return Response(f.read(), mimetype=mimetype)
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py", line 749, in __init__
    mimetype = get_content_type(mimetype, self.charset)
  File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/utils.py", line 224, in get_content_type
    if mimetype.startswith('text/') or \
TypeError: startswith first arg must be bytes or a tuple of bytes, not str
bug

Hilfreichster Kommentar

Hallo, dies passiert oft, wenn das Paket django-extensions wie oben erwähnt verwendet wird. Dies wurde seit fast 2 Jahren nicht mehr angerührt. Gibt es ein Problem beim Zusammenführen des verknüpften MR?

Alle 10 Kommentare

eingereichte PR, die das Problem behebt

Ich bin mir nicht sicher, ob dies an Werkzeug liegt oder Django in seinen Antworten falsche Zeichenfolgentypen verwendet.

Hier ist der vollständige Traceback in ipdb und ich sehe nicht, dass Django nirgendwo aufgerufen wird. Kompletter Stackstace scheint nur in werkzeug zu sein.

ipdb> w
  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(692)inner()
    690         make_server(hostname, port, application, threaded,
    691                     processes, request_handler,
--> 692                     passthrough_errors, ssl_context).serve_forever()
    693 
    694     if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(436)serve_forever()
    434         self.shutdown_signal = False
    435         try:
--> 436             HTTPServer.serve_forever(self)
    437         except KeyboardInterrupt:
    438             pass

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(238)serve_forever()
    236                                        poll_interval)
    237                 if self in r:
--> 238                     self._handle_request_noblock()
    239 
    240                 self.service_actions()

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(305)_handle_request_noblock()
    303         if self.verify_request(request, client_address):
    304             try:
--> 305                 self.process_request(request, client_address)
    306             except:
    307                 self.handle_error(request, client_address)

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(331)process_request()
    329 
    330         """
--> 331         self.finish_request(request, client_address)
    332         self.shutdown_request(request)
    333 

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(344)finish_request()
    342     def finish_request(self, request, client_address):
    343         """Finish one request by instantiating RequestHandlerClass."""
--> 344         self.RequestHandlerClass(request, client_address, self)
    345 
    346     def shutdown_request(self, request):

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(669)__init__()
    667         self.setup()
    668         try:
--> 669             self.handle()
    670         finally:
    671             self.finish()

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(200)handle()
    198         rv = None
    199         try:
--> 200             rv = BaseHTTPRequestHandler.handle(self)
    201         except (socket.error, socket.timeout) as e:
    202             self.connection_dropped(e)

  /usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/server.py(398)handle()
    396         self.close_connection = 1
    397 
--> 398         self.handle_one_request()
    399         while not self.close_connection:
    400             self.handle_one_request()

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(235)handle_one_request()
    233             self.close_connection = 1
    234         elif self.parse_request():
--> 235             return self.run_wsgi()
    236 
    237     def send_response(self, code, message=None):

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(177)run_wsgi()
    175 
    176         try:
--> 177             execute(self.server.app)
    178         except (socket.error, socket.timeout) as e:
    179             self.connection_dropped(e, environ)

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(165)execute()
    163 
    164         def execute(app):
--> 165             application_iter = app(environ, start_response)
    166             try:
    167                 for data in application_iter:

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(173)__call__()
    171             frame = self.frames.get(request.args.get('frm', type=int))
    172             if cmd == 'resource' and arg:
--> 173                 response = self.get_resource(request, arg)
    174             elif cmd == 'paste' and traceback is not None and \
    175                  secret == self.secret:

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(154)get_resource()
    152             f = open(filename, 'rb')
    153             try:
--> 154                 return Response(f.read(), mimetype=mimetype)
    155             finally:
    156                 f.close()

  /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py(749)__init__()
    747                 mimetype = self.default_mimetype
    748             if mimetype is not None:
--> 749                 mimetype = get_content_type(mimetype, self.charset)
    750             content_type = mimetype
    751         if content_type is not None:

> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/utils.py(224)get_content_type()
    222     #     charset = charset.decode('utf-8')
    223     import ipdb; ipdb.set_trace()
--> 224     if mimetype.startswith('text/') or \
    225        mimetype == 'application/xml' or \
    226        (mimetype.startswith('application/') and

ipdb> type(mimetype), type(charset)
(<class 'bytes'>, <class 'str'>)

Das Problem scheint in 2 Frames oben zu liegen:

ipdb> up
> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py(749)__init__()
    748             if mimetype is not None:
--> 749                 mimetype = get_content_type(mimetype, self.charset)
    750             content_type = mimetype

ipdb> up
> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(154)get_resource()
    153             try:
--> 154                 return Response(f.read(), mimetype=mimetype)
    155             finally:

ipdb> l
    149         if isfile(filename):
    150             mimetype = mimetypes.guess_type(filename)[0] \
    151                 or 'application/octet-stream'
    152             f = open(filename, 'rb')
    153             try:
--> 154                 return Response(f.read(), mimetype=mimetype)
    155             finally:
    156                 f.close()
    157         return Response('Not Found', status=404)
    158 
    159     def __call__(self, environ, start_response):

ipdb> mimetypes.guess_type(filename)[0]
b'text/javascript'

Seltsam ist, dass guess_type Bytes vs String zurückgibt. Wenn ich versuche, den Typ für dieselbe Datei in der Shell zu erraten, erhalte ich eine Zeichenfolge:

>>> mimetype = mimetypes.guess_type('/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/shared/jquery.js')[0]
>>> type(mimetype)
<class 'str'>

Sollte ich PR anpassen, um Mimetype hier anstatt in get_content_type() umzuwandeln?

Seltsam ist, dass Vermutung_Typ Bytes vs String zurückgibt

Ihr PR behebt das Problem, aber das hätte nie passieren dürfen, wie Sie sagten.

Was ist der Dateiname in dem Frame, in dem der guess_type Aufruf stattfindet?

seine Saite. Ich dachte, dass guess_type vielleicht denselben Typ wie Dateiname zurückgibt, aber anscheinend nicht der Fall ist.

Hallo, dies passiert oft, wenn das Paket django-extensions wie oben erwähnt verwendet wird. Dies wurde seit fast 2 Jahren nicht mehr angerührt. Gibt es ein Problem beim Zusammenführen des verknüpften MR?

Vor kurzem habe ich das gleiche Problem, bei mir passiert es bei Javascript-Dateien. Nach dem Debuggen stellte ich fest, dass mein Problem django-pipeline war: Es ändert die types_map und setzt diese https://github.com/jazzband/django-pipeline/blob/master/pipeline/conf.py#L81 -L87 hier https://github.com/jazzband/django-pipeline/blob/master/pipeline/utils.py#L42 -L43 .. :S :S ... um das Problem zu lösen, musste ich nur MIMETYPES in meinen Pipeline-Einstellungen richtig einstellen .

Vielleicht sollten Sie das Zusammenführen der PR überdenken.

Hoffe, das hilft jemandem ... viel Spaß beim Debuggen!

Django-Pipelines sollten behoben werden, damit keine Bytes in die Mimetype-Typ-Map eingefügt werden. Django-Extensions scheint nichts zu tun, aber das bedeutet nur, dass sich eine andere Abhängigkeit falsch verhält. Ich schließe dies, da ich denke, dass es in den Bibliotheken behoben werden sollte, die die schlechten Daten hinzufügen. Wenn jemand einen guten Grund dafür posten kann, dass Bytes in der Mimetypes-Typenkarte erwartet werden sollten, werde ich es mir noch einmal überlegen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen