TypeError: a bytes-like object is required, not 'str' when writing to a file in Python 3

TypeError: a bytes-like object is required, not 'str' when writing to a file in Python 3

我最近迁移到了 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: a bytes-like object is required, not 'str'

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

我试过在语句的两边使用 .decode() 函数,还试过:

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

- 无济于事。

我能够快速解决几乎所有 Python 2 到 Python 3 个问题,但这个小声明让我很烦。

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

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):
        break
    print (data);

mysock.close()

What does the 'b' character do in front of a string literal?

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

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

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'])

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

来源:How to remove ^M

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

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

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

此外,这是官方页面上 Python 3.x 的 link: io — Core tools for working with streams.

这是打开函数: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())

我在尝试将字符(或字符串)转换为 bytes 时遇到此错误,代码与 Python 2.7 类似:

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

这是Python 2.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