TypeError: Python3 में एक फाइल पर लिखते समय एक बाइट्स जैसी ऑब्जेक्ट की आवश्यकता होती है, न कि when str ’की


590

मैंने हाल ही में Py 3.5 में माइग्रेट किया है। पायथन 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

- कोई फायदा नहीं।

मैं लगभग सभी 2: 3 मुद्दों को जल्दी से हल करने में सक्षम था, लेकिन यह छोटा सा बयान मुझे परेशान कर रहा है।


11
आप फ़ाइल को बाइनरी मोड में क्यों खोल रहे हैं लेकिन इसे टेक्स्ट के रूप में मानते हैं?
मार्टिन पीटर्स

4
@MartijnPieters फ़ाइल ओपन मोड को खोलने के लिए धन्यवाद! इसे टेक्स्ट-मोड में बदलने से समस्या हल हो गई ... कोड ने कई वर्षों तक Py2k में मज़बूती से काम किया था ...
masroore


10
मैं यह भी सामना कर रहा हूं जहां मेरे पास एक अनुरोध है result = requests.getऔर मैं करने का प्रयास करता हूं x = result.content.split("\n")। मैं त्रुटि संदेश से थोड़ा भ्रमित हूं क्योंकि यह प्रतीत होता है कि result.contentयह एक स्ट्रिंग है और .split()बाइट्स जैसी वस्तु की आवश्यकता है .. ?? ("बाइट्स जैसी वस्तु की आवश्यकता है, 'str' नहीं))

जवाबों:


553

आपने फ़ाइल को बाइनरी मोड में खोला है:

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'


12
यदि आप पीपीएल से जुड़े विभिन्न दस्तावेजों को देखते हैं, तो आप देखेंगे कि Py2 में "सब कुछ" काम किया है क्योंकि डिफ़ॉल्ट स्ट्रिंग्स बाइट्स थे जबकि Py3 में, डिफ़ॉल्ट स्ट्रिंग्स यूनिकोड हैं, जिसका अर्थ है कि आप किसी भी समय I / O कर रहे हैं, esp। नेटवर्किंग, बाइट स्ट्रिंग्स मानक हैं, इसलिए आपको बी / डब्ल्यू यूनिकोड और बाइट्स स्ट्रिंग्स (एन / डायोड) को स्थानांतरित करना सीखना चाहिए। फ़ाइलों के लिए, अब हमारे पास "आर" बनाम "आरबी" (और 'डब्ल्यू' और 'ए') के लिए अंतर करने में मदद करने के लिए है।
वेस्कपी

3
@wescpy: पायथन 2 में भी'r' बनाम , द्विआधारी और पाठ फ़ाइल व्यवहारों के बीच स्विच करना (जैसे नईलाइनों का अनुवाद करना और कुछ प्लेटफार्मों पर, ईओएफ मार्कर का इलाज कैसे किया जाता है)। यही कारण है कि पुस्तकालय (अजगर 2 में अजगर 3 में डिफ़ॉल्ट आई / ओ कार्यक्षमता पर भी उपलब्ध उपलब्ध कराने) अब भी डीकोड डिफ़ॉल्ट रूप से पाठ फ़ाइलों वास्तविक परिवर्तन है। 'rb' io
मार्टिन पीटर्स

2
@MartijnPieters: हाँ, सहमत हैं। 2.x में, मैंने केवल 'b'DOS / Windows पर बाइनरी फ़ाइलों के साथ काम करने के दौरान ध्वज का उपयोग किया था (जैसा कि बाइनरी POSIX डिफ़ॉल्ट है)। यह अच्छा है कि ioफ़ाइल एक्सेस के लिए 3.x में उपयोग करते समय एक दोहरे उद्देश्य है ।
wescpy

207

आप का उपयोग करके अपने स्ट्रिंग सांकेतिक शब्दों में बदलना कर सकते हैं .encode()

उदाहरण:

'Hello World'.encode()

48

जैसे यह पहले ही उल्लेख किया गया है, आप फ़ाइल को बाइनरी मोड में पढ़ रहे हैं और फिर बाइट्स की एक सूची बना रहे हैं। लूप के लिए आपके अनुसरण में आप स्ट्रिंग को बाइट्स से तुलना कर रहे हैं और वह वह जगह है जहां कोड विफल हो रहा है।

सूची में जोड़ते समय बाइट्स को डिकोड करना काम करना चाहिए। परिवर्तित कोड इस प्रकार दिखना चाहिए:

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

बाइट्स प्रकार पायथन 3 में पेश किया गया था और यही कारण है कि आपके कोड ने पायथन 2 में काम किया। पायथन 2 में बाइट्स के लिए कोई डेटा प्रकार नहीं था:

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

25

आपको 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'])

इसे बदलने के बाद, त्रुटि गायब हो जाती है, लेकिन आप फ़ाइल में नहीं लिख सकते हैं (मेरे मामले में)। तो आखिरकार, मेरे पास कोई जवाब नहीं है?

स्रोत: ^ एम कैसे निकालें

'आरबी' में बदलने से मुझे दूसरी त्रुटि मिलती है: io.UnsupportedOperation: लिखना


15

इस छोटे उदाहरण के लिए: आयात सॉकेट

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()

"GET http://www.py4inf.com/code/romeo.txt HTTP / 1.0 \ n \ n " से पहले "b" जोड़ने से मेरी समस्या हल हो गई


11

एक उद्धरण में दिए गए हार्डकोड स्ट्रिंग मूल्य के साथ एन्कोड () फ़ंक्शन का उपयोग करें।

उदाहरण के लिए:

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

या

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

8

आपने फ़ाइल को बाइनरी मोड में खोला है:

निम्न कोड TypeError को फेंक देगा: एक बाइट्स की तरह ऑब्जेक्ट की आवश्यकता है, न कि 'str'।

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

निम्नलिखित कोड काम करेगा - आपको डिकोड () फ़ंक्शन का उपयोग करना होगा:

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

4

पाठ के रूप में अपनी फ़ाइल खोलने का प्रयास क्यों न करें?

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

इसके अतिरिक्त यहाँ आधिकारिक पृष्ठ पर python 3.x के लिए एक लिंक है: https://docs.python.org/3/library/io.html और यह खुला कार्य है: https://docs.python.org/3 /library/functions.html#open

यदि आप वास्तव में इसे एक बाइनरी के रूप में संभालने की कोशिश कर रहे हैं, तो अपने स्ट्रिंग को एन्कोड करने पर विचार करें।


1

मुझे यह त्रुटि तब मिली जब मैं एक चार (या स्ट्रिंग) को बदलने की कोशिश कर रहा था bytes, कोड कुछ इस तरह था पायथन 2.7 2.7:

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

यह पायथन 2.7 का तरीका है यूनिकोड वर्णों से निपटने ।

यह पायथन 3.6 के साथ काम नहीं करेगा, क्योंकि bytesएन्कोडिंग के लिए एक अतिरिक्त तर्क की आवश्यकता होती है, लेकिन यह थोड़ा मुश्किल हो सकता है, क्योंकि विभिन्न एन्कोडिंग अलग हो सकते हैं:

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

मेरे मामले में मुझे इस्तेमाल करना था iso_8859_1 इस मुद्दे को हल करने के लिए बाइट्स एन्कोडिंग समय ।

आशा है कि यह किसी की मदद करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.