[Python] 运行Flask, 报错:UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 33: ordinal not in range(128)

运行时报错:UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 33: ordinal not in range(128)

 

Python2.7在Windows上一个bug!!!

解决方法:

 

参考官方patch: http://bugs.python.org/file19332/9291a.patch

如下代码:一,加入from itertools import count;

                  二,修改 def enum_types(mimedb)为

 

                         def enum_types(mimedb):

                              for i in count():

                           try:

                                 yield _winreg.EnumKey(mimedb, i)

                          except EnvironmentError:

                                   break

 

具体代码如下(直接复制就好):

  1 """Guess the MIME type of a file.
  2 
  3 This module defines two useful functions:
  4 
  5 guess_type(url, strict=1) -- guess the MIME type and encoding of a URL.
  6 
  7 guess_extension(type, strict=1) -- guess the extension for a given MIME type.
  8 
  9 It also contains the following, for tuning the behavior:
 10 
 11 Data:
 12 
 13 knownfiles -- list of files to parse
 14 inited -- flag set when init() has been called
 15 suffix_map -- dictionary mapping suffixes to suffixes
 16 encodings_map -- dictionary mapping suffixes to encodings
 17 types_map -- dictionary mapping suffixes to types
 18 
 19 Functions:
 20 
 21 init([files]) -- parse a list of files, default knownfiles (on Windows, the
 22   default values are taken from the registry)
 23 read_mime_types(file) -- parse one file, return a dictionary or None
 24 """
 25 from itertools import count
 26 import os
 27 import sys
 28 import posixpath
 29 import urllib
 30 try:
 31   import _winreg
 32 except ImportError:
 33   _winreg = None
 34 
 35 __all__ = [
 36   "guess_type","guess_extension","guess_all_extensions",
 37   "add_type","read_mime_types","init"
 38 ]
 39 
 40 knownfiles = [
 41   "/etc/mime.types",
 42   "/etc/httpd/mime.types",                    # Mac OS X
 43   "/etc/httpd/conf/mime.types",               # Apache
 44   "/etc/apache/mime.types",                   # Apache 1
 45   "/etc/apache2/mime.types",                  # Apache 2
 46   "/usr/local/etc/httpd/conf/mime.types",
 47   "/usr/local/lib/netscape/mime.types",
 48   "/usr/local/etc/httpd/conf/mime.types",     # Apache 1.2
 49   "/usr/local/etc/mime.types",                # Apache 1.3
 50   ]
 51 
 52 inited = False
 53 _db = None
 54 
 55 
 56 class MimeTypes:
 57   """MIME-types datastore.
 58 
 59   This datastore can handle information from mime.types-style files
 60   and supports basic determination of MIME type from a filename or
 61   URL, and can guess a reasonable extension given a MIME type.
 62   """
 63 
 64   def __init__(self, filenames=(), strict=True):
 65     if not inited:
 66       init()
 67     self.encodings_map = encodings_map.copy()
 68     self.suffix_map = suffix_map.copy()
 69     self.types_map = ({}, {}) # dict for (non-strict, strict)
 70     self.types_map_inv = ({}, {})
 71     for (ext, type) in types_map.items():
 72       self.add_type(type, ext, True)
 73     for (ext, type) in common_types.items():
 74       self.add_type(type, ext, False)
 75     for name in filenames:
 76       self.read(name, strict)
 77 
 78   def add_type(self, type, ext, strict=True):
 79     """Add a mapping between a type and an extension.
 80 
 81     When the extension is already known, the new
 82     type will replace the old one. When the type
 83     is already known the extension will be added
 84     to the list of known extensions.
 85 
 86     If strict is true, information will be added to
 87     list of standard types, else to the list of non-standard
 88     types.
 89     """
 90     self.types_map[strict][ext] = type
 91     exts = self.types_map_inv[strict].setdefault(type, [])
 92     if ext not in exts:
 93       exts.append(ext)
 94 
 95   def guess_type(self, url, strict=True):
 96     """Guess the type of a file based on its URL.
 97 
 98     Return value is a tuple (type, encoding) where type is None if
 99     the type can't be guessed (no or unknown suffix) or a string
100     of the form type/subtype, usable for a MIME Content-type
101     header; and encoding is None for no encoding or the name of
102     the program used to encode (e.g. compress or gzip).  The
103     mappings are table driven.  Encoding suffixes are case
104     sensitive; type suffixes are first tried case sensitive, then
105     case insensitive.
106 
107     The suffixes .tgz, .taz and .tz (case sensitive!) are all
108     mapped to '.tar.gz'.  (This is table-driven too, using the
109     dictionary suffix_map.)
110 
111     Optional `strict' argument when False adds a bunch of commonly found,
112     but non-standard types.
113     """
114     scheme, url = urllib.splittype(url)
115     if scheme == 'data':
116       # syntax of data URLs:
117       # dataurl   := "data:" [ mediatype ] [ ";base64" ] "," data
118       # mediatype := [ type "/" subtype ] *( ";" parameter )
119       # data      := *urlchar
120       # parameter := attribute "=" value
121       # type/subtype defaults to "text/plain"
122       comma = url.find(',')
123       if comma < 0:
124         # bad data URL
125         return None, None
126       semi = url.find(';', 0, comma)
127       if semi >= 0:
128         type = url[:semi]
129       else:
130         type = url[:comma]
131       if '=' in type or '/' not in type:
132         type = 'text/plain'
133       return type, None           # never compressed, so encoding is None
134     base, ext = posixpath.splitext(url)
135     while ext in self.suffix_map:
136       base, ext = posixpath.splitext(base + self.suffix_map[ext])
137     if ext in self.encodings_map:
138       encoding = self.encodings_map[ext]
139       base, ext = posixpath.splitext(base)
140     else:
141       encoding = None
142     types_map = self.types_map[True]
143     if ext in types_map:
144       return types_map[ext], encoding
145     elif ext.lower() in types_map:
146       return types_map[ext.lower()], encoding
147     elif strict:
148       return None, encoding
149     types_map = self.types_map[False]
150     if ext in types_map:
151       return types_map[ext], encoding
152     elif ext.lower() in types_map:
153       return types_map[ext.lower()], encoding
154     else:
155       return None, encoding
156 
157   def guess_all_extensions(self, type, strict=True):
158     """Guess the extensions for a file based on its MIME type.
159 
160     Return value is a list of strings giving the possible filename
161     extensions, including the leading dot ('.').  The extension is not
162     guaranteed to have been associated with any particular data stream,
163     but would be mapped to the MIME type `type' by guess_type().
164 
165     Optional `strict' argument when false adds a bunch of commonly found,
166     but non-standard types.
167     """
168     type = type.lower()
169     extensions = self.types_map_inv[True].get(type, [])
170     if not strict:
171       for ext in self.types_map_inv[False].get(type, []):
172         if ext not in extensions:
173           extensions.append(ext)
174     return extensions
175 
176   def guess_extension(self, type, strict=True):
177     """Guess the extension for a file based on its MIME type.
178 
179     Return value is a string giving a filename extension,
180     including the leading dot ('.').  The extension is not
181     guaranteed to have been associated with any particular data
182     stream, but would be mapped to the MIME type `type' by
183     guess_type().  If no extension can be guessed for `type', None
184     is returned.
185 
186     Optional `strict' argument when false adds a bunch of commonly found,
187     but non-standard types.
188     """
189     extensions = self.guess_all_extensions(type, strict)
190     if not extensions:
191       return None
192     return extensions[0]
193 
194   def read(self, filename, strict=True):
195     """
196     Read a single mime.types-format file, specified by pathname.
197 
198     If strict is true, information will be added to
199     list of standard types, else to the list of non-standard
200     types.
201     """
202     with open(filename) as fp:
203       self.readfp(fp, strict)
204 
205   def readfp(self, fp, strict=True):
206     """
207     Read a single mime.types-format file.
208 
209     If strict is true, information will be added to
210     list of standard types, else to the list of non-standard
211     types.
212     """
213     while 1:
214       line = fp.readline()
215       if not line:
216         break
217       words = line.split()
218       for i in range(len(words)):
219         if words[i][0] == '#':
220           del words[i:]
221           break
222       if not words:
223         continue
224       type, suffixes = words[0], words[1:]
225       for suff in suffixes:
226         self.add_type(type, '.' + suff, strict)
227 
228   def read_windows_registry(self, strict=True):
229     """
230     Load the MIME types database from Windows registry.
231 
232     If strict is true, information will be added to
233     list of standard types, else to the list of non-standard
234     types.
235     """
236 
237     # Windows only
238     if not _winreg:
239       return
240 
241     def enum_types(mimedb):
242       for i in count():
243         try:
244           yield _winreg.EnumKey(mimedb, i)
245         except EnvironmentError:
246           break
247     #def enum_types(mimedb):
248       #  i = 0
249        # while True:
250        #     try:
251       #        ctype = _winreg.EnumKey(mimedb, i)
252       #    except EnvironmentError:
253        #       break
254        #   try:
255        #       ctype = ctype.encode(default_encoding) # omit in 3.x!
256        #   except UnicodeEncodeError:
257        #       pass
258        #   else:
259        #       yield ctype
260        #   i += 1
261 
262     default_encoding = sys.getdefaultencoding()
263     with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, '') as hkcr:
264       for subkeyname in enum_types(hkcr):
265         try:
266           with _winreg.OpenKey(hkcr, subkeyname) as subkey:
267             # Only check file extensions
268             if not subkeyname.startswith("."):
269               continue
270             # raises EnvironmentError if no 'Content Type' value
271             mimetype, datatype = _winreg.QueryValueEx(
272               subkey, 'Content Type')
273             if datatype != _winreg.REG_SZ:
274               continue
275             try:
276               mimetype = mimetype.encode(default_encoding)
277               subkeyname = subkeyname.encode(default_encoding)
278             except UnicodeEncodeError:
279               continue
280             self.add_type(mimetype, subkeyname, strict)
281         except EnvironmentError:
282           continue
283 
284 def guess_type(url, strict=True):
285   """Guess the type of a file based on its URL.
286 
287   Return value is a tuple (type, encoding) where type is None if the
288   type can't be guessed (no or unknown suffix) or a string of the
289   form type/subtype, usable for a MIME Content-type header; and
290   encoding is None for no encoding or the name of the program used
291   to encode (e.g. compress or gzip).  The mappings are table
292   driven.  Encoding suffixes are case sensitive; type suffixes are
293   first tried case sensitive, then case insensitive.
294 
295   The suffixes .tgz, .taz and .tz (case sensitive!) are all mapped
296   to ".tar.gz".  (This is table-driven too, using the dictionary
297   suffix_map).
298 
299   Optional `strict' argument when false adds a bunch of commonly found, but
300   non-standard types.
301   """
302   if _db is None:
303     init()
304   return _db.guess_type(url, strict)
305 
306 
307 def guess_all_extensions(type, strict=True):
308   """Guess the extensions for a file based on its MIME type.
309 
310   Return value is a list of strings giving the possible filename
311   extensions, including the leading dot ('.').  The extension is not
312   guaranteed to have been associated with any particular data
313   stream, but would be mapped to the MIME type `type' by
314   guess_type().  If no extension can be guessed for `type', None
315   is returned.
316 
317   Optional `strict' argument when false adds a bunch of commonly found,
318   but non-standard types.
319   """
320   if _db is None:
321     init()
322   return _db.guess_all_extensions(type, strict)
323 
324 def guess_extension(type, strict=True):
325   """Guess the extension for a file based on its MIME type.
326 
327   Return value is a string giving a filename extension, including the
328   leading dot ('.').  The extension is not guaranteed to have been
329   associated with any particular data stream, but would be mapped to the
330   MIME type `type' by guess_type().  If no extension can be guessed for
331   `type', None is returned.
332 
333   Optional `strict' argument when false adds a bunch of commonly found,
334   but non-standard types.
335   """
336   if _db is None:
337     init()
338   return _db.guess_extension(type, strict)
339 
340 def add_type(type, ext, strict=True):
341   """Add a mapping between a type and an extension.
342 
343   When the extension is already known, the new
344   type will replace the old one. When the type
345   is already known the extension will be added
346   to the list of known extensions.
347 
348   If strict is true, information will be added to
349   list of standard types, else to the list of non-standard
350   types.
351   """
352   if _db is None:
353     init()
354   return _db.add_type(type, ext, strict)
355 
356 
357 def init(files=None):
358   global suffix_map, types_map, encodings_map, common_types
359   global inited, _db
360   inited = True    # so that MimeTypes.__init__() doesn't call us again
361   db = MimeTypes()
362   if files is None:
363     if _winreg:
364       db.read_windows_registry()
365     files = knownfiles
366   for file in files:
367     if os.path.isfile(file):
368       db.read(file)
369   encodings_map = db.encodings_map
370   suffix_map = db.suffix_map
371   types_map = db.types_map[True]
372   common_types = db.types_map[False]
373   # Make the DB a global variable now that it is fully initialized
374   _db = db
375 
376 
377 def read_mime_types(file):
378   try:
379     f = open(file)
380   except IOError:
381     return None
382   db = MimeTypes()
383   db.readfp(f, True)
384   return db.types_map[True]
385 
386 
387 def _default_mime_types():
388   global suffix_map
389   global encodings_map
390   global types_map
391   global common_types
392 
393   suffix_map = {
394     '.tgz': '.tar.gz',
395     '.taz': '.tar.gz',
396     '.tz': '.tar.gz',
397     '.tbz2': '.tar.bz2',
398     '.txz': '.tar.xz',
399     }
400 
401   encodings_map = {
402     '.gz': 'gzip',
403     '.Z': 'compress',
404     '.bz2': 'bzip2',
405     '.xz': 'xz',
406     }
407 
408   # Before adding new types, make sure they are either registered with IANA,
409   # at http://www.isi.edu/in-notes/iana/assignments/media-types
410   # or extensions, i.e. using the x- prefix
411 
412   # If you add to these, please keep them sorted!
413   types_map = {
414     '.a'      : 'application/octet-stream',
415     '.ai'     : 'application/postscript',
416     '.aif'    : 'audio/x-aiff',
417     '.aifc'   : 'audio/x-aiff',
418     '.aiff'   : 'audio/x-aiff',
419     '.au'     : 'audio/basic',
420     '.avi'    : 'video/x-msvideo',
421     '.bat'    : 'text/plain',
422     '.bcpio'  : 'application/x-bcpio',
423     '.bin'    : 'application/octet-stream',
424     '.bmp'    : 'image/x-ms-bmp',
425     '.c'      : 'text/plain',
426     # Duplicates :(
427     '.cdf'    : 'application/x-cdf',
428     '.cdf'    : 'application/x-netcdf',
429     '.cpio'   : 'application/x-cpio',
430     '.csh'    : 'application/x-csh',
431     '.css'    : 'text/css',
432     '.dll'    : 'application/octet-stream',
433     '.doc'    : 'application/msword',
434     '.dot'    : 'application/msword',
435     '.dvi'    : 'application/x-dvi',
436     '.eml'    : 'message/rfc822',
437     '.eps'    : 'application/postscript',
438     '.etx'    : 'text/x-setext',
439     '.exe'    : 'application/octet-stream',
440     '.gif'    : 'image/gif',
441     '.gtar'   : 'application/x-gtar',
442     '.h'      : 'text/plain',
443     '.hdf'    : 'application/x-hdf',
444     '.htm'    : 'text/html',
445     '.html'   : 'text/html',
446     '.ico'    : 'image/vnd.microsoft.icon',
447     '.ief'    : 'image/ief',
448     '.jpe'    : 'image/jpeg',
449     '.jpeg'   : 'image/jpeg',
450     '.jpg'    : 'image/jpeg',
451     '.js'     : 'application/javascript',
452     '.ksh'    : 'text/plain',
453     '.latex'  : 'application/x-latex',
454     '.m1v'    : 'video/mpeg',
455     '.man'    : 'application/x-troff-man',
456     '.me'     : 'application/x-troff-me',
457     '.mht'    : 'message/rfc822',
458     '.mhtml'  : 'message/rfc822',
459     '.mif'    : 'application/x-mif',
460     '.mov'    : 'video/quicktime',
461     '.movie'  : 'video/x-sgi-movie',
462     '.mp2'    : 'audio/mpeg',
463     '.mp3'    : 'audio/mpeg',
464     '.mp4'    : 'video/mp4',
465     '.mpa'    : 'video/mpeg',
466     '.mpe'    : 'video/mpeg',
467     '.mpeg'   : 'video/mpeg',
468     '.mpg'    : 'video/mpeg',
469     '.ms'     : 'application/x-troff-ms',
470     '.nc'     : 'application/x-netcdf',
471     '.nws'    : 'message/rfc822',
472     '.o'      : 'application/octet-stream',
473     '.obj'    : 'application/octet-stream',
474     '.oda'    : 'application/oda',
475     '.p12'    : 'application/x-pkcs12',
476     '.p7c'    : 'application/pkcs7-mime',
477     '.pbm'    : 'image/x-portable-bitmap',
478     '.pdf'    : 'application/pdf',
479     '.pfx'    : 'application/x-pkcs12',
480     '.pgm'    : 'image/x-portable-graymap',
481     '.pl'     : 'text/plain',
482     '.png'    : 'image/png',
483     '.pnm'    : 'image/x-portable-anymap',
484     '.pot'    : 'application/vnd.ms-powerpoint',
485     '.ppa'    : 'application/vnd.ms-powerpoint',
486     '.ppm'    : 'image/x-portable-pixmap',
487     '.pps'    : 'application/vnd.ms-powerpoint',
488     '.ppt'    : 'application/vnd.ms-powerpoint',
489     '.ps'     : 'application/postscript',
490     '.pwz'    : 'application/vnd.ms-powerpoint',
491     '.py'     : 'text/x-python',
492     '.pyc'    : 'application/x-python-code',
493     '.pyo'    : 'application/x-python-code',
494     '.qt'     : 'video/quicktime',
495     '.ra'     : 'audio/x-pn-realaudio',
496     '.ram'    : 'application/x-pn-realaudio',
497     '.ras'    : 'image/x-cmu-raster',
498     '.rdf'    : 'application/xml',
499     '.rgb'    : 'image/x-rgb',
500     '.roff'   : 'application/x-troff',
501     '.rtx'    : 'text/richtext',
502     '.sgm'    : 'text/x-sgml',
503     '.sgml'   : 'text/x-sgml',
504     '.sh'     : 'application/x-sh',
505     '.shar'   : 'application/x-shar',
506     '.snd'    : 'audio/basic',
507     '.so'     : 'application/octet-stream',
508     '.src'    : 'application/x-wais-source',
509     '.sv4cpio': 'application/x-sv4cpio',
510     '.sv4crc' : 'application/x-sv4crc',
511     '.swf'    : 'application/x-shockwave-flash',
512     '.t'      : 'application/x-troff',
513     '.tar'    : 'application/x-tar',
514     '.tcl'    : 'application/x-tcl',
515     '.tex'    : 'application/x-tex',
516     '.texi'   : 'application/x-texinfo',
517     '.texinfo': 'application/x-texinfo',
518     '.tif'    : 'image/tiff',
519     '.tiff'   : 'image/tiff',
520     '.tr'     : 'application/x-troff',
521     '.tsv'    : 'text/tab-separated-values',
522     '.txt'    : 'text/plain',
523     '.ustar'  : 'application/x-ustar',
524     '.vcf'    : 'text/x-vcard',
525     '.wav'    : 'audio/x-wav',
526     '.wiz'    : 'application/msword',
527     '.wsdl'   : 'application/xml',
528     '.xbm'    : 'image/x-xbitmap',
529     '.xlb'    : 'application/vnd.ms-excel',
530     # Duplicates :(
531     '.xls'    : 'application/excel',
532     '.xls'    : 'application/vnd.ms-excel',
533     '.xml'    : 'text/xml',
534     '.xpdl'   : 'application/xml',
535     '.xpm'    : 'image/x-xpixmap',
536     '.xsl'    : 'application/xml',
537     '.xwd'    : 'image/x-xwindowdump',
538     '.zip'    : 'application/zip',
539     }
540 
541   # These are non-standard types, commonly found in the wild.  They will
542   # only match if strict=0 flag is given to the API methods.
543 
544   # Please sort these too
545   common_types = {
546     '.jpg' : 'image/jpg',
547     '.mid' : 'audio/midi',
548     '.midi': 'audio/midi',
549     '.pct' : 'image/pict',
550     '.pic' : 'image/pict',
551     '.pict': 'image/pict',
552     '.rtf' : 'application/rtf',
553     '.xul' : 'text/xul'
554     }
555 
556 
557 _default_mime_types()
558 
559 
560 if __name__ == '__main__':
561   import getopt
562 
563   USAGE = """\
564 Usage: mimetypes.py [options] type
565 
566 Options:
567   --help / -h       -- print this message and exit
568   --lenient / -l    -- additionally search of some common, but non-standard
569              types.
570   --extension / -e  -- guess extension instead of type
571 
572 More than one type argument may be given.
573 """
574 
575   def usage(code, msg=''):
576     print USAGE
577     if msg: print msg
578     sys.exit(code)
579 
580   try:
581     opts, args = getopt.getopt(sys.argv[1:], 'hle',
582                    ['help', 'lenient', 'extension'])
583   except getopt.error, msg:
584     usage(1, msg)
585 
586   strict = 1
587   extension = 0
588   for opt, arg in opts:
589     if opt in ('-h', '--help'):
590       usage(0)
591     elif opt in ('-l', '--lenient'):
592       strict = 0
593     elif opt in ('-e', '--extension'):
594       extension = 1
595   for gtype in args:
596     if extension:
597       guess = guess_extension(gtype, strict)
598       if not guess: print "I don't know anything about type", gtype
599       else: print guess
600     else:
601       guess, encoding = guess_type(gtype, strict)
602       if not guess: print "I don't know anything about type", gtype
603       else: print 'type:', guess, 'encoding:', encoding

 

posted @ 2015-04-30 21:38  virqin  阅读(5189)  评论(0编辑  收藏  举报