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

TypeError:需要类似字节的对象,而不是';str';在Python3中写入文件时,python,python-3.x,string,file,byte,Python,Python 3.x,String,File,Byte,我最近迁移到了Py 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 # -*- coding: utf-8 -*- print( b

我最近迁移到了Py 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
# -*- coding: utf-8 -*-
print( bytes('ò') )
升级到3.5后,我得到:

TypeError: a bytes-like object is required, not 'str'
最后一行错误(模式搜索代码)

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

if tmp.find('some-pattern') != -1: continue
-无济于事


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

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

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

if 'some-pattern' in tmp: continue
您必须使用
bytes
对象来测试
tmp

if b'some-pattern' in tmp: continue

或者将
'rb'
模式替换为
'r'

以文本文件的形式打开该文件,例如:

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()
导入套接字
mysock=socket.socket(socket.AF\u INET,socket.SOCK\u流)
connect(('www.py4inf.com',80))
mysock.send(**b**'GEThttp://www.py4inf.com/code/romeo.txt HTTP/1.0\n\n')
尽管如此:
data=mysock.recv(512)
如果(len(数据)<1):
打破
打印(数据);
mysock.close()
在前面加上“b” '获取HTTP/1.0\n\n'
解决了我的问题

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

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

with open(fname, 'rb') as f:
    lines = [x.decode('utf8').strip() for x in f.readlines()]
字节类型是在Python3中引入的,这就是代码在Python2中工作的原因。在Python 2中,字节没有数据类型:

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

您可以使用
.encode()

例如:

'Hello World'.encode()

您必须从wb更改为w:

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

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

资料来源:


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

为什么不尝试以文本形式打开文件

with open(fname, 'rt') as f:
    lines = [x.strip() for x in f.readlines()]
此外,在官方页面上还有一个python 3.x的链接: 这是开放式功能:


如果你真的想用二进制来处理它,那么就考虑对你的字符串进行编码。

你用二进制模式打开了文件:

with open(fname, 'rb') as f:
下面的代码将抛出 类型错误:需要类似字节的对象,而不是“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')
对于行中的行:
line=line.decode()
打印(类型(行))#
如果行中有“子字符串”:
打印(‘成功’)
将encode()函数与单引号中给定的硬编码字符串值一起使用

例:


当我试图将字符(或字符串)转换为
字节时,出现了这个错误,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
# -*- coding: utf-8 -*-
print( bytes('ò') )
这是处理unicode字符时的方法

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

print( bytes('ò', 'iso_8859_1') ) # prints: b'\xf2'
print( bytes('ò', 'utf-8') ) # prints: b'\xc3\xb2'
在我的例子中,为了解决这个问题,在编码字节时我不得不使用
iso_8859_1


希望这对其他人有所帮助。

为什么要以二进制模式打开文件,而将其视为文本?@MartijnPieters感谢您发现了文件打开模式!将其更改为文本模式解决了此问题。。。代码在Py2k中可靠地工作了很多年,但是…@masroore请看:我也遇到了这种情况,我有一个请求
result=requests.get
,我尝试
x=result.content.split(“\n”)
。我对错误消息感到有点困惑,因为它似乎暗示
result.content
是一个字符串,而
.split()
需要一个类似于object.的字节。。??(“需要一个类似字节的对象,而不是'str')。如果你浏览一下ppl链接到的各种文档,你会发现在Py2中一切都“正常”,因为默认字符串是字节,而在Py3中,默认字符串是Unicode,这意味着在进行I/O的任何时候,尤其是在联网时,字节字符串都是标准的,因此,您必须学习移动b/w Unicode和字节字符串(en/decode)。对于文件,我们现在有“r”和“rb”(以及“w”和“a”)来帮助区分。@wescpy:Python2也有
'r'
vs
'rb'
,在二进制和文本文件行为之间切换(如翻译换行符和在某些平台上如何处理EOF标记)。
io
库(在Python 3中提供默认的I/O功能,但在Python 2中也可用)现在默认情况下也解码文本文件,这才是真正的变化。@MartijnPieters:是的,同意。在2.x中,当必须在DOS/Windows上处理二进制文件时,我只使用了
'b'
标志(因为二进制是POSIX的默认值)。在3.x中使用
io
进行文件访问时,有一个双重用途是很好的。@ericOnline
ZipFile.open()
docs(以类似二进制文件的对象访问归档文件的成员)。您可以将文件对象包装起来以达到相同的效果。@此外,当您可以直接迭代文件对象时,不要使用
.readlines()
。特别是当你只需要一行信息的时候。为什么要在第一个缓冲块中找到信息时将所有内容都读入内存呢?Python 2确实有一个字节类型,它只是被混淆地称为
str
,而文本字符串的类型被称为
unicode
。在Python3中,他们更改了
str
的含义,使其与旧的
unicode
类型相同,并将旧的
str
重命名为
bytes