Xlsxwriter:TypeError:“期望的string或缓冲区”

我有这样的例外,如标题中所述,当试图从查询过滤的模型生成一个Excel文件。 查询按预期工作,并给我正确和完整的结果。 但是,当我尝试实际生成excel文件时,发生了一件大事:

File "/home/luismasuelli/Proyectos/CentralCar/main/views.py", line 100, in export_xls workbook.close() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/workbook.py", line 237, in close self._store_workbook() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/workbook.py", line 405, in _store_workbook xml_files = packager._create_package() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/packager.py", line 139, in _create_package self._write_shared_strings_file() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/packager.py", line 265, in _write_shared_strings_file sst._assemble_xml_file() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/sharedstrings.py", line 53, in _assemble_xml_file self._write_sst_strings() File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/sharedstrings.py", line 83, in _write_sst_strings self._write_si(string) File "/home/luismasuelli/.virtualenvs/py27dj15/local/lib/python2.7/site-packages/xlsxwriter/sharedstrings.py", line 95, in _write_si string = re.sub('(_x[0-9a-fA-F]{4}_)', r'_x005F\1', string) File "/home/luismasuelli/.virtualenvs/py27dj15/lib/python2.7/re.py", line 151, in sub return _compile(pattern, flags).sub(repl, string, count) TypeError: expected string or buffer 

什么可能导致我这个例外? 我试图改变编码,把utf8作为build议,但是这并没有帮助我在这里。

我正在从django应用程序使用Xlsxwriter 0.5.2 / python 2.7.4(ubuntu),如下所示:

 # -*- coding: utf8 -*- #... from StringIO import StringIO #... import datetime #... from django.http import HttpResponse, Http404 #... import xlsxwriter #... from main.models import Contact #... def export_xls(request, period=''): deltas = { 'D': datetime.timedelta(days=1), 'W': datetime.timedelta(days=7), 'M': datetime.timedelta(days=30), '6M': datetime.timedelta(days=182), 'Y': datetime.timedelta(days=365) } query = Contact.objects.all().order_by('-enviado_en') if period: query = query.filter(enviado_en__gt=datetime.datetime.now() - deltas[period]) stream = StringIO() workbook = xlsxwriter.Workbook(stream, {'in_memory': True}) worksheet = workbook.add_worksheet('Contactos') #poner encabezados header_format = workbook.add_format() header_format.set_align("center") header_format.set_bold() header_format.set_font_name('Arial') worksheet.set_column(9, 9, 40) worksheet.write_string(0, 0, Contact._meta.get_field('enviado_en').verbose_name, header_format) worksheet.write_string(0, 1, Contact._meta.get_field('nombre').verbose_name, header_format) worksheet.write_string(0, 2, Contact._meta.get_field('apellido').verbose_name, header_format) worksheet.write_string(0, 3, Contact._meta.get_field('email').verbose_name, header_format) worksheet.write_string(0, 4, Contact._meta.get_field('telefono').verbose_name, header_format) worksheet.write_string(0, 5, Contact._meta.get_field('ciudad').verbose_name, header_format) worksheet.write_string(0, 6, Contact._meta.get_field('vehiculo').verbose_name, header_format) worksheet.write_string(0, 7, Contact._meta.get_field('kilometraje').verbose_name, header_format) worksheet.write_string(0, 8, Contact._meta.get_field('dia_preferente').verbose_name, header_format) worksheet.write_string(0, 9, Contact._meta.get_field('mensaje').verbose_name, header_format) #poner cada fila body_format = workbook.add_format() body_format.set_font_name('Arial') current_row = 1 for contact in query: worksheet.write(current_row, 0, contact.enviado_en.strftime("%d/%m/%Y %H/%M/%S"), body_format) worksheet.write(current_row, 1, contact.nombre, body_format) worksheet.write(current_row, 2, contact.apellido, body_format) worksheet.write(current_row, 3, contact.email, body_format) worksheet.write(current_row, 4, contact.telefono, body_format) worksheet.write(current_row, 5, contact.ciudad, body_format) worksheet.write(current_row, 6, contact.get_vehiculo_display(), body_format) worksheet.write(current_row, 7, contact.get_kilometraje_display(), body_format) worksheet.write(current_row, 8, contact.get_dia_preferente_display(), body_format) worksheet.write(current_row, 9, contact.mensaje, body_format) current_row += 1 workbook.close() data = stream.getvalue() response = HttpResponse(content=data, content_type='application/vnd.ms-excel') response['Content-Disposition'] = 'attachment; filename=reporte-%s.xlsx' % datetime.datetime.now().strftime("%Y%m%d%H%M%S") return response 

成为我的模特联系人:

 class Contact(models.Model): DIAS = ( #('?', 'Cualquiera'), ('L', 'Lunes'), ('M', 'Martes'), ('I', 'Miercoles'), ('J', 'Jueves'), ('V', 'Viernes'), ('S', 'Sábado') ) KILOMETRAJE = ( #('??', '(No especifica)'), ('00', '0km'), ('05', '1 - 5000km'), ('10', '5000km - 10000km'), ('15', '10001km - 15000km'), ('20', '15001km - 20000km'), ('25', '20001km - 25000km'), ('30', '25001km - 30000km'), ('35', '30001km - 35000km'), ('40', '35001km - 40000km'), ('45', '40001km - 45000km'), ('50', '45001km - 50000km'), ('55', '50001km - 55000km'), ('60', '55001km - 60000km'), ('65', '60001km - 65000km'), ('70', '65001km - 70000km'), ('75', '70001km - 75000km'), ('80', '75001km - 80000km'), ('85', '80001km - 85000km'), ('90', '85001km - 90000km'), ('95', '90001km - 950000km'), ('XX', '95001km - 100000km'), ('++', 'Más de 100000km') ) enviado_en = models.DateTimeField(default=tznow, null=False, db_index=True, verbose_name=_(u"Enviado en")) #campos de contacto nombre = models.CharField(max_length=30, null=False, blank=False, db_index=True, verbose_name=_(u"Nombre")) apellido = models.CharField(max_length=30, null=False, blank=False, db_index=True, verbose_name=_(u"Apellido")) email = models.EmailField(null=False, blank=False, db_index=True, verbose_name=_(u"E-mail")) telefono = models.CharField(max_length=10, null=False, blank=False, db_index=True, validators=[contact_phone_number_format], verbose_name=_(u"Teléfono")) ciudad = models.CharField(max_length=20, null=False, blank=False, validators=[validate_ciudad], verbose_name=_(u"Ciudad")) #campos solamente de cotizacion vehiculo = models.CharField(max_length=20, blank=True, db_index=True, choices=vehicle_choices(), verbose_name=_(u"Vehículo")) kilometraje = models.CharField(max_length=2, blank=True, db_index=True, choices=KILOMETRAJE, default='05', verbose_name=_(u"Kilometraje")) #campos solamente de agendar cita dia_preferente = models.CharField(max_length=1, blank=True, choices=DIAS, default='L', verbose_name=_(u'Día para cita')) #mensaje mensaje = models.TextField(max_length=4095, null=False, blank=False, verbose_name=_(u"Mensaje")) 

假设存在vehicle_choices()并为input字段返回一个有效的select集。

我find了答案:实际上,verbose_name对象是从ugettext_lazy返回的代理。 调用force_unicode(ugl_obj)将它们转换为string(转换不是自动完成的)。

在我的情况下,打印头中的每个值都被打包,例如:

  worksheet.write_string(0, 0, force_unicode(Contact._meta.get_field('enviado_en').verbose_name), header_format)