Jag har nyligen övergått till Py 3.5. Den här koden fungerade korrekt i Python 2.7:
with open(fname, 'rb') as f:
lines = [x.strip() for x in f.readlines()]
for line in lines:
tmp = line.strip().lower()
if 'some-pattern' in tmp: continue
# ... code
Efter att ha uppgraderat till 3.5 får jag följande:
TypeError: a bytes-like object is required, not 'str'
fel på sista raden (koden för mönstersökning).
Jag har försökt att använda funktionen .decode()
på båda sidor av uttalandet, och jag har också försökt:
if tmp.find('some-pattern') != -1: continue
- utan resultat.
Jag kunde lösa nästan alla 2:3-problem snabbt, men det här lilla uttalandet stör mig.
Du öppnade filen i binärt läge:
with open(fname, 'rb') as f:
Detta innebär att alla data som läses från filen returneras som bytes
-objekt, inte str
. Du kan alltså inte använda en sträng i ett inneslutningstest:
if 'some-pattern' in tmp: continue
Du måste använda ett bytes
-objekt för att testa mot tmp
istället:
if b'some-pattern' in tmp: continue
eller öppna filen som en textfil istället genom att ersätta läget 'rb'
med 'r'
.
Som redan nämnts läser du filen i binärt läge och skapar sedan en lista med bytes. I din följande for-slinga jämför du strängen med bytes och det är där koden misslyckas.
Avkodning av bytes medan du lägger till i listan bör fungera. Den ändrade koden bör se ut på följande sätt:
with open(fname, 'rb') as f:
lines = [x.decode('utf8').strip() for x in f.readlines()]
Bytes-typen infördes i Python 3 och det är därför din kod fungerade i Python 2. I Python 2 fanns det ingen datatyp för bytes:
>>> s=bytes('hello')
>>> type(s)
<type 'str'>
för detta lilla exempel: import socket
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect(('www.py4inf.com', 80))
mysock.send(**b**'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n')
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
print (data);
mysock.close()
lägga till "b" före 'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n' löste mitt problem