पाइथन में UTF-8 फ़ाइल में लिखें


204

मैं वास्तव में उलझन में हूँ codecs.open function। जब मैं करता हूं:

file = codecs.open("temp", "w", "utf-8")
file.write(codecs.BOM_UTF8)
file.close()

यह मुझे त्रुटि देता है

यूनिकोडडॉफॉर्सेट: 'एससीआई' कोडक 0xef को 0xef से कम नहीं कर सकता है। क्रम में नहीं (128)

यदि मैं करता हूँ:

file = open("temp", "w")
file.write(codecs.BOM_UTF8)
file.close()

यह बढ़िया काम करता है।

प्रश्न यह है कि पहला तरीका विफल क्यों होता है? और मैं बम कैसे डालूं?

यदि दूसरी विधि इसे करने का सही तरीका है, तो उपयोग करने का क्या मतलब है codecs.open(filename, "w", "utf-8") ?


54
UTF-8 में BOM का उपयोग न करें। कृप्या।
tchrist

7
@ टिश्र्ट हुह? क्यों नहीं?
सलमान ने अब्बास

8
@SalmanPK BOM की यूटीएफ -8 में जरूरत नहीं है और केवल जटिलता जोड़ता है (जैसे कि आप बस BOM'd फ़ाइलों को समाप्‍त नहीं कर सकते हैं और मान्य पाठ के साथ परिणाम कर सकते हैं)। इस प्रश्नोत्तर देखें ; Q
एलोइस महदल

जवाबों:


271

मेरा मानना ​​है कि समस्या यही है codecs.BOM_UTF8 बाइट स्ट्रिंग है, यूनिकोड स्ट्रिंग नहीं। मुझे संदेह है कि फ़ाइल हैंडलर यह अनुमान लगाने की कोशिश कर रहा है कि आप वास्तव में "यूएनएफ को यूटीएफ -8-एन्कोडेड पाठ के रूप में लिखने के लिए क्या है, पर आधारित है, लेकिन आपने मुझे एक बाइट स्ट्रिंग दिया है!"

बाइट ऑर्डर मार्क (यानी यूनिकोड यू + फीफ़) के लिए यूनिकोड स्ट्रिंग को सीधे लिखने की कोशिश करें, ताकि फ़ाइल बस यूटीएफ -8 के रूप में एनकोड करें:

import codecs

file = codecs.open("lol", "w", "utf-8")
file.write(u'\ufeff')
file.close()

(यह सही जवाब देने के लिए लगता है - बाइट्स के साथ एक फाइल ईएफ बीबी बीएफ।)

संपादित करें: एन्कोडिंग के रूप में "utf-8-sig" का उपयोग करने का एस। लोट्ट का सुझाव खुद को BOM लिखने से बेहतर है, लेकिन मैं इस उत्तर को यहां छोड़ दूंगा क्योंकि यह बताता है कि पहले क्या गलत हो रहा था।


चेतावनी: खुला और खुला समान नहीं है। यदि आप "कोडेक्स इंपोर्ट ओपन से" करते हैं, तो यह वैसा नहीं होगा जैसा आप "ओपन" टाइप करेंगे।
Apache

2
इसके बजाय आप codecs.open ('test.txt', 'w', 'utf-8-sig') का उपयोग कर सकते हैं
बीटा-बंद

1
मुझे "TypeError: एक पूर्णांक आवश्यक है (टाइप स्ट्रिंग मिला)"। मुझे समझ नहीं आ रहा है कि हम यहाँ क्या कर रहे हैं। क्या कोई मदद कर सकता है? मुझे एक स्ट्रिंग (पैराग्राफ) को एक पाठ फ़ाइल में संलग्न करना होगा। क्या मुझे लिखने से पहले इसे पूर्णांक में बदलना होगा?
मुगें

@Mugen: मैंने जो लिखा है, ठीक वही कोड ठीक है जहाँ तक मैं देख सकता हूँ। मेरा सुझाव है कि आप एक नया प्रश्न पूछें जिसमें दिखाया गया है कि आपको क्या कोड मिला है, और त्रुटि कहां हुई है।
जॉन स्कीट

@ अब आपको codecs.openसिर्फ कॉल करने की ज़रूरत हैopen
नॉर्थबेन

179

निम्नलिखित को पढ़ें: http://docs.python.org/library/codecs.html#module-encodings.utf_8_sig

यह करो

with codecs.open("test_output", "w", "utf-8-sig") as temp:
    temp.write("hi mom\n")
    temp.write(u"This has ♭")

परिणामी फ़ाइल अपेक्षित BOM के साथ UTF-8 है।


2
धन्यवाद। यह काम किया (विंडोज 7 x64, पायथन 2.7.5 x64)। जब आप फ़ाइल को मोड "a" (append) में खोलते हैं तो यह समाधान अच्छी तरह से काम करता है।
मोहम्मद फकीह

यह मेरे लिए, विंडोज पर पायथन 3 के लिए काम नहीं करता था। मुझे इसके बजाय ओपन (file_name, 'wb') के साथ बॉम्फाइल: बॉमफाइल.राइट (कोडेक्स .BOM_UTF8) के साथ करना था, फिर एपेंड के लिए फाइल को फिर से खोलें।
डस्टिन एंड्रयूज

शायद जोड़ सकते हैं temp.close()?
user2905353

2
@ user2905353: आवश्यक नहीं; इस द्वारा नियंत्रित किया जाता संदर्भ प्रबंधन की open
मथेबर्ग

11

@ एस-लोट सही प्रक्रिया देता है, लेकिन यूनिकोड मुद्दों पर विस्तार करते हुए , पायथन दुभाषिया अधिक अंतर्दृष्टि प्रदान कर सकता है।

जॉन स्कीट codecsमॉड्यूल के बारे में सही (असामान्य) है - इसमें बाइट स्ट्रिंग्स शामिल हैं:

>>> import codecs
>>> codecs.BOM
'\xff\xfe'
>>> codecs.BOM_UTF8
'\xef\xbb\xbf'
>>> 

एक और नाइट चुनना, BOMएक मानक यूनिकोड नाम है, और इसे निम्न रूप में दर्ज किया जा सकता है:

>>> bom= u"\N{ZERO WIDTH NO-BREAK SPACE}"
>>> bom
u'\ufeff'

यह इसके माध्यम से भी सुलभ है unicodedata:

>>> import unicodedata
>>> unicodedata.lookup('ZERO WIDTH NO-BREAK SPACE')
u'\ufeff'
>>> 

8

मैं एक अज्ञात charset फ़ाइल को utf-8 फ़ाइल में बदलने के लिए फ़ाइल * निक्स कमांड का उपयोग करता हूं

# -*- encoding: utf-8 -*-

# converting a unknown formatting file in utf-8

import codecs
import commands

file_location = "jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)

file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')

for l in file_stream:
    file_output.write(l)

file_stream.close()
file_output.close()

1
# coding: utf8इसके बजाय का उपयोग करें # -*- coding: utf-8 -*-जो याद रखना बहुत आसान है।
शो '10
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.