TypeError:在Python 3中写入文件时需要类似字节的对象,而不是'str'

我最近迁移到Python 3.5。此代码在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

升级到3.5后,我得到了:

TypeError:需要一个类似字节的对象,而不是'str'

错误在最后一行(模式搜索代码)。

我已经尝试在语句的两边使用.decode()函数,并且还尝试了:

if tmp.find('some-pattern') != -1: continue

-无济于事。

我能够快速解决几乎所有Python 2到Python 3的问题,但这个小声明困扰着我。

1967873 次浏览

您以二进制模式打开文件:

with open(fname, 'rb') as f:

这意味着从文件中读取的所有数据都作为bytes对象返回,而不是str。然后,您不能在包含测试中使用字符串:

if 'some-pattern' in tmp: continue

你必须使用bytes对象来测试tmp

if b'some-pattern' in tmp: continue

或者将文件作为文本文件打开,而不是将'rb'模式替换为'r'

对于这个小例子,在前面添加唯一的b'GET http://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n'解决了我的问题:

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):breakprint (data);
mysock.close()

字符串文字前面的'b'字符做什么?

就像已经提到的那样,您正在以二进制模式读取文件,然后创建一个字节列表。在下面的进行循环中,您正在比较字符串和字节,这就是代码失败的地方。

在添加到列表时解码字节应该可以。更改后的代码应如下所示:

with open(fname, 'rb') as f:lines = [x.decode('utf8').strip() for x in f.readlines()]

bytes类型是在Python 3中引入的,这就是为什么您的代码在Python 2中工作。在Python 2中,字节没有数据类型:

>>> s=bytes('hello')>>> type(s)<type 'str'>

您可以使用.encode()对字符串进行编码

示例:

'Hello World'.encode()

正如错误所描述的,为了将字符串写入文件,您需要首先将其编码为类似字节的对象,而encode()将其编码为字节字符串。

您必须从wb更改为w:

def __init__(self):self.myCsv = csv.writer(open('Item.csv', 'wb'))self.myCsv.writerow(['title', 'link'])

def __init__(self):self.myCsv = csv.writer(open('Item.csv', 'w'))self.myCsv.writerow(['title', 'link'])

更改后,错误消失,但您无法写入文件(在我的情况下)。所以,毕竟,我没有答案?

来源:如何删除^M

更改为'rb'给我带来了另一个错误:io

尝试以文本形式打开您的文件:

with open(fname, 'rt') as f:lines = [x.strip() for x in f.readlines()]

此外,这是官方页面上Python 3. x的链接:iOS-用于处理流的核心工具.

这是open函数:打开

如果您真的试图将其作为二进制处理,那么请考虑对字符串进行编码。

您以二进制模式打开文件:

以下代码将抛出TypeError:需要一个类似字节的对象,而不是'str'。

for line in lines:print(type(line))# <class 'bytes'>if 'substring' in line:print('success')

以下代码将起作用-您必须使用decode()函数:

for line in lines:line = line.decode()print(type(line))# <class 'str'>if 'substring' in line:print('success')

使用encode()函数以及单引号中给出的硬编码字符串值。

示例:

file.write(answers[i] + '\n'.encode())

line.split(' +++$+++ '.encode())

当我试图将char(或字符串)转换为bytes时,我遇到了这个错误,Python 2.7的代码是这样的:

# -*- coding: utf-8 -*-print(bytes('ò'))

这是python2.7处理Unicode字符的方式。

这在Python 3.6中不起作用,因为bytes需要额外的参数进行编码,但这可能有点棘手,因为不同的编码可能会输出不同的结果:

print(bytes('ò', 'iso_8859_1')) # prints: b'\xf2'print(bytes('ò', 'utf-8')) # prints: b'\xc3\xb2'

在我的情况下,我不得不在编码字节时使用iso_8859_1来解决这个问题。