builtins.TypeError: deve ser str, não bytes

220

Eu converti meus scripts do Python 2.7 para 3.2 e tenho um bug.

# -*- coding: utf-8 -*-
import time
from datetime import date
from lxml import etree
from collections import OrderedDict

# Create the root element
page = etree.Element('results')

# Make a new document tree
doc = etree.ElementTree(page)

# Add the subelements
pageElement = etree.SubElement(page, 'Country',Tim = 'Now', 
                                      name='Germany', AnotherParameter = 'Bye',
                                      Code='DE',
                                      Storage='Basic')
pageElement = etree.SubElement(page, 'City', 
                                      name='Germany',
                                      Code='PZ',
                                      Storage='Basic',AnotherParameter = 'Hello')
# For multiple multiple attributes, use as shown above

# Save to XML file
outFile = open('output.xml', 'w')
doc.write(outFile) 

Na última linha, recebi este erro:

builtins.TypeError: must be str, not bytes
File "C:\PythonExamples\XmlReportGeneratorExample.py", line 29, in <module>
  doc.write(outFile)
File "c:\Python32\Lib\site-packages\lxml\etree.pyd", line 1853, in lxml.etree._ElementTree.write (src/lxml/lxml.etree.c:44355)
File "c:\Python32\Lib\site-packages\lxml\etree.pyd", line 478, in lxml.etree._tofilelike (src/lxml/lxml.etree.c:90649)
File "c:\Python32\Lib\site-packages\lxml\etree.pyd", line 282, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:7972)
File "c:\Python32\Lib\site-packages\lxml\etree.pyd", line 378, in lxml.etree._FilelikeWriter.write (src/lxml/lxml.etree.c:89527)

Instalei o Python 3.2 e instalei o lxml-2.3.win32-py3.2.exe.

No Python 2.7, ele funciona.

user278618
fonte
10
Realmente não investigou isso, mas um palpite rápido é que você deve abrir o arquivo no modo binário.
Sven Marnach 01/04

Respostas:

483

O arquivo de saída deve estar no modo binário.

outFile = open('output.xml', 'wb')
Lennart Regebro
fonte
100
Mente soprada. Python3 reinventou o que fazer com esse pequeno 'b'. Ele costumava incomodar os usuários do Windows que se esqueciam de incluí-lo (ou não podiam porque estavam usando o stdio). Agora ele pode incomodar usuários de Python em todas as plataformas. Felizmente, valerá a pena.
Nobar
5
Se você estiver analisando texto, definitivamente vale a pena.
Lennart Regebro
@nobar É necessário, por exemplo desligar suporte de nova linha Universal, legacy.python.org/dev/peps/pep-0278 , que é ligado por padrão em Python 3
user7610
Funciona para mim no gzip para python3 também! json.load(gzip.open('file.json.gz'))falha e json.load(gzip.open('file.json.gz', 'rt'))consegue!
hobs
@LennartRegebro, Não se a configuração do sistema for inesperada. O binário é melhor e menos propenso a erros. Se funcionar, realmente funciona. Quanto ao texto, sempre há um "e se" envolvido.
Pacerier 16/02
6

Converta arquivo binário em base64 e vice-versa. Prove no python 3.5.2

import base64

read_file = open('/tmp/newgalax.png', 'rb')
data = read_file.read()

b64 = base64.b64encode(data)

print (b64)

# Save file
decode_b64 = base64.b64decode(b64)
out_file = open('/tmp/out_newgalax.png', 'wb')
out_file.write(decode_b64)

# Test in python 3.5.2
djperalta
fonte