我最近迁移到了Python3.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中,在tmp:contain行中的if“some pattern”上,我得到一个错误,该错误表示:

TypeError: a bytes-like object is required, not 'str'

我无法在in的任一侧使用.dedecode()解决问题,也无法使用

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

有什么问题,我该如何解决?


当前回答

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

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

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

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

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

其他回答

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

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

此外,在官方页面上还有Python 3.x的链接:io-处理流的核心工具。

这就是open函数:open

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

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

例子:

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

Or

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

你必须从wb改为w:

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

to

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

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

来源:如何删除^M

更改为“rb”会给我带来另一个错误:io.UnsupportedOperation:write

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

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

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

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

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

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

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

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

if 'some-pattern' in tmp: continue

您必须使用一个字节对象来测试tmp:

if b'some-pattern' in tmp: continue

或将“rb”模式替换为“r”,将文件作为文本文件打开。