पाठ फ़ाइल में यूनिकोड पाठ लिखना?


225

मैं एक Google दस्तावेज़ से डेटा खींच रहा हूं, इसे संसाधित कर रहा हूं और इसे एक फ़ाइल में लिख रहा हूं (आखिरकार मैं एक वर्डप्रेस पेज में पेस्ट करूंगा)।

इसके कुछ गैर-एएससीआईआई प्रतीक हैं। HTML स्रोत में उपयोग किए जा सकने वाले प्रतीकों को मैं कैसे सुरक्षित रूप से परिवर्तित कर सकता हूं?

वर्तमान में मैं रास्ते में यूनिकोड में सब कुछ परिवर्तित कर रहा हूं, इसे पायथन स्ट्रिंग में एक साथ जोड़ रहा हूं, फिर कर रहा हूं:

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

अंतिम पंक्ति में एन्कोडिंग त्रुटि है:

यूनिकोडडॉफॉर्सेट: 'एससीआई' कोडक 0xa0 को 12286 की स्थिति में बाइट नहीं कर सकता: ऑर्डिनल रेंज में नहीं (128)

आंशिक समाधान:

यह पायथन त्रुटि के बिना चलता है:

row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8"))

लेकिन फिर अगर मैं वास्तविक पाठ फ़ाइल खोलता हूं, तो मुझे बहुत सारे प्रतीक दिखाई देते हैं जैसे:

Qur’an 

शायद मुझे एक पाठ फ़ाइल के अलावा कुछ और लिखने की ज़रूरत है?


1
प्रोग्राम जिसे आप खोलने के लिए उपयोग कर रहे हैं, वह UTF-8 पाठ की सही ढंग से व्याख्या नहीं कर रहा है। फ़ाइल को UTF-8 के रूप में खोलने का विकल्प होना चाहिए।
थॉमस के

जवाबों:


322

विशेष रूप से यूनिकोड ऑब्जेक्ट्स के साथ डील करें जितना संभव हो यूनिकोड ऑब्जेक्ट्स को डिकोड करके संभव है जब आप पहली बार उन्हें प्राप्त करते हैं और बाहर निकलने के रास्ते में आवश्यक रूप से एन्कोडिंग करते हैं।

यदि आपकी स्ट्रिंग वास्तव में एक यूनिकोड ऑब्जेक्ट है, तो फ़ाइल पर लिखने से पहले आपको इसे यूनिकोड-एन्कोडेड स्ट्रिंग ऑब्जेक्ट में बदलना होगा:

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

जब आप उस फ़ाइल को दोबारा पढ़ते हैं, तो आपको एक यूनिकोड-एन्कोडेड स्ट्रिंग मिलेगी जिसे आप एक यूनिकोड ऑब्जेक्ट को डिकोड कर सकते हैं:

f = file('test', 'r')
print f.read().decode('utf8')

धन्यवाद। यह एक त्रुटि के बिना चलता है, लेकिन फिर अगर मैं पाठ फ़ाइल को खोलता हूं, तो मुझे अजीब प्रतीकों का एक गुच्छा दिखाई देता है :) मुझे पाठ को एक Wordpress पृष्ठ में कॉपी करने और पेस्ट करने की आवश्यकता है (पूछें नहीं)। क्या कोई तरीका है जो मैं वास्तव में प्रतीकों को प्रिंट कर सकता हूं? मुझे लगता है कि एक txt फ़ाइल के लिए नहीं, सही, लेकिन शायद कुछ और करने के लिए?
सिमोन

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

@quasistoic फ़ाइल विधि कहाँ से आती है?
उमर कुसमा आस्था

जैसा कि stackoverflow.com/a/5513856/6580199 में वर्णित है, अन्यथा मुझे बाइनरी मोड को चालू करने की आवश्यकता है, f (ओपन ('टेस्ट', 'wb') - अन्यथा मुझे "TypeError: write () तर्क मिलना चाहिए। बाइट्स नहीं "
बेंजी

72

पायथन 2.6+ में, आप पायथन 3 पर डिफ़ॉल्ट ( बिलिन ) का उपयोगio.open() कर सकते हैं :open()

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

यदि आप पाठ को वृहद रूप से लिखने की आवश्यकता है (आपको unicode_text.encode(character_encoding)कई बार कॉल करने की आवश्यकता नहीं है ) तो यह अधिक सुविधाजनक हो सकता है । codecsमॉड्यूल के विपरीत , ioमॉड्यूल में एक उचित सार्वभौमिक न्यूलाइन्स समर्थन है।


1
यार, मैंने इसे खोजने के लिए बहुत समय बिताया! धन्यवाद!
जार्ज गोब्जोव

2
यह पायथन 3 के लिए भी काम करता है (स्पष्ट, लेकिन अभी भी इंगित करने के लायक है)।
हिप्पो

37

पायथन 3 में यूनिकोड स्ट्रिंग हैंडलिंग पहले से ही मानकीकृत है।

  1. मेमोरी में चार पहले से ही यूनिकोड (32-बिट) में संग्रहीत हैं
  2. आपको केवल utf-8 में फ़ाइल खोलने की आवश्यकता है
    (32-बिट यूनिकोड को चर-बाइट-लंबाई utf-8 रूपांतरण में स्वचालित रूप से मेमोरी से फ़ाइल में किया जाता है।)

    out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
    fobj = open("t1.txt", "w", encoding="utf-8")
    fobj.write(out1)
    fobj.close()

लेकिन यह पायथन 2 पर काम नहीं करता है, है ना? (मुझे कहना चाहिए, इस पायथन 3 कोड पर, यह इतना संक्षिप्त और उचित लगता है)
लीवेन झाओ

यह अजगर 2 पर काम नहीं करना चाहिए। हम अजगर 3 पर रहते हैं। 3 इतना बेहतर है।
david m lee

18

द्वारा खोली गई codecs.openफ़ाइल एक ऐसी फ़ाइल है जो unicodeडेटा लेती है, इसे इसमें एनकोड करती है iso-8859-1और इसे फ़ाइल में लिखती है। हालाँकि, आप जो लिखने का प्रयास करते हैं वह नहीं है unicode; आप unicodeइसे iso-8859-1 अपने आप में ले लेते हैं और एनकोड करते हैं । यह unicode.encodeविधि क्या करती है, और एक यूनिकोड स्ट्रिंग एन्कोडिंग का परिणाम एक बाइटस्ट्रिंग (एक strप्रकार) है।

आपको या तो सामान्य का उपयोग करना चाहिए open()और स्वयं यूनिकोड को एनकोड करना चाहिए , या (आमतौर पर एक बेहतर विचार) का उपयोग करें codecs.open()और डेटा को स्वयं एनकोड करें।


17

प्रस्तावना: क्या आपका दर्शक काम करेगा?

सुनिश्चित करें कि आपका दर्शक / संपादक / टर्मिनल (हालाँकि आप अपनी utf-8 एन्कोडेड फ़ाइल के साथ सहभागिता कर रहे हैं) फ़ाइल को पढ़ सकते हैं। यह अक्सर विंडोज पर एक मुद्दा है , उदाहरण के लिए, नोटपैड।

पाठ फ़ाइल में यूनिकोड पाठ लिखना?

पायथन 2 में, मॉड्यूल openसे उपयोग करें io(यह openपायथन 3 में बिलिन के समान है ):

import io

सर्वोत्तम अभ्यास, सामान्य रूप से, UTF-8फ़ाइलों को लिखने के लिए उपयोग करें (हमें utf-8 के साथ बाइट-ऑर्डर के बारे में चिंता करने की ज़रूरत नहीं है)।

encoding = 'utf-8'

utf-8 सबसे आधुनिक और सार्वभौमिक रूप से प्रयोग करने योग्य एन्कोडिंग है - यह सभी वेब ब्राउज़र, अधिकांश टेक्स्ट-एडिटर्स (यदि आपकी समस्या है तो अपनी सेटिंग्स देखें) और अधिकांश टर्मिनलों / गोले में काम करता है।

utf-16leयदि आप नोटपैड (या किसी अन्य सीमित दर्शक) में आउटपुट देखने तक सीमित हैं , तो विंडोज पर, आप कोशिश कर सकते हैं।

encoding = 'utf-16le' # sorry, Windows users... :(

और बस इसे संदर्भ प्रबंधक के साथ खोलें और अपने यूनिकोड वर्णों को लिखें:

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

कई यूनिकोड वर्णों का उपयोग करके उदाहरण

यहां एक उदाहरण दिया गया है जो तीन बिट्स तक विस्तृत हर संभावित चरित्र को मैप करने का प्रयास करता है (4 अधिकतम है, लेकिन डिजिटल प्रतिनिधित्व से एक एनकोडेड प्रिन्टेबल आउटपुट में, इसके नाम के साथ, अगर यह थोड़ा सा हो तो) संभव (इसे एक फ़ाइल में कहा जाता है uni.py):

from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter

try: # use these if Python 2
    unicode_chr, range = unichr, xrange
except NameError: # Python 3
    unicode_chr = chr

exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
    for x in range((2**8)**3): 
        try:
            char = unicode_chr(x)
        except ValueError:
            continue # can't map to unicode, try next x
        cat = category(char)
        counts.update((cat,))
        if cat in exclude_categories:
            continue # get rid of noise & greatly shorten result file
        try:
            uname = name(char)
        except ValueError: # probably control character, don't use actual
            uname = control_names.get(x, '')
            f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
    print('{0} chars of category, {1}'.format(count, cat))

यह लगभग एक मिनट के क्रम में चलना चाहिए, और आप डेटा फ़ाइल देख सकते हैं, और यदि आपका फ़ाइल दर्शक यूनिकोड प्रदर्शित कर सकता है, तो आप इसे देख पाएंगे। श्रेणियों के बारे में जानकारी यहाँ मिल सकती है । गिनती के आधार पर, हम संभवतः Cn और Co श्रेणियों को छोड़कर हमारे परिणामों में सुधार कर सकते हैं, जिनके साथ कोई प्रतीक नहीं जुड़ा है।

$ python uni.py

यह हेक्साडेसिमल मैपिंग, श्रेणी , प्रतीक (जब तक कि नाम नहीं मिल सकता है, तो संभवतः एक नियंत्रण चरित्र), और प्रतीक का नाम प्रदर्शित करेगा। जैसे

मैं lessयूनिक्स या साइगविन पर सलाह देता हूं (अपने आउटपुट में संपूर्ण फ़ाइल को प्रिंट / कैट न करें):

$ less unidata

उदाहरण निम्न पंक्तियों के समान होगा जो मैंने इसे पायथन 2 (यूनिकोड 5.2) का उपयोग करके नमूना किया था:

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So    PILCROW SIGN
    d0 Lu  Ð  LATIN CAPITAL LETTER ETH
   e59 Nd    THAI DIGIT NINE
  2887 So    BRAILLE PATTERN DOTS-1238
  bc13 Lo    HANGUL SYLLABLE MIH
  ffeb Sm    HALFWIDTH RIGHTWARDS ARROW

एनाकोंडा से मेरे पायथन 3.5 में यूनिकोड 8.0 है, मैं सबसे अधिक 3-का अनुमान लगाऊंगा।


3

फ़ाइल में यूनिकोड वर्ण कैसे प्रिंट करें:

इसे फ़ाइल में सहेजें: foo.py:

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys 
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')

इसे चलाने के लिए और फाइल करने के लिए पाइप आउटपुट:

python foo.py > tmp.txt

Tmp.txt खोलें और अंदर देखें, आप इसे देखते हैं:

el@apollo:~$ cat tmp.txt 
e with obfuscation: é

इस प्रकार आपने यूनिकोड ई को एक फ़ाइल पर एक ऑबफ्यूज़ेशन मार्क के साथ सहेजा है।


2
मैं इस उत्तर के बारे में बहुत उत्साहित था, लेकिन यह मेरी मशीन पर एक त्रुटि देता है। जब मैं आपके कोड को कॉपी / पेस्ट करता हूं, तो मुझे एक त्रुटि मिलती है: "TypeError: str होना चाहिए, बाइट्स नहीं"
रिचर्ड रास्ट

1

जब आप एक गैर-यूनिकोड स्ट्रिंग को एन्कोड करने का प्रयास करते हैं तो यह त्रुटि उत्पन्न होती है: यह इसे सादे डिकोडी में मानते हुए इसे डिकोड करने का प्रयास करता है। दो संभावनाएँ हैं:

  1. आप इसे एक बाइटस्ट्रिंग में एन्कोडिंग कर रहे हैं, लेकिन क्योंकि आपने कोडेकस्पेस का उपयोग किया है, लिखने की विधि एक यूनिकोड ऑब्जेक्ट की अपेक्षा करती है। तो आप इसे एनकोड करते हैं, और इसे फिर से डिकोड करने की कोशिश करता है। f.write(all_html)इसके बजाय कोशिश करें ।
  2. all_html, वास्तव में, एक यूनिकोड ऑब्जेक्ट नहीं है। जब आप करते हैं .encode(...), तो यह पहले इसे डिकोड करने की कोशिश करता है।

0

Python3 में लिखने के मामले में

>>> a = u'bats\u00E0'
>>> print a
batsà
>>> f = open("/tmp/test", "w")
>>> f.write(a)
>>> f.close()
>>> data = open("/tmp/test").read()
>>> data
'batsà'

Python2 में लिखने के मामले में:

>>> a = u'bats\u00E0'
>>> f = open("/tmp/test", "w")
>>> f.write(a)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

इस त्रुटि से बचने के लिए आपको कोडेक्स "utf-8" का उपयोग करके इसे बाइट्स में बदलना होगा:

>>> f.write(a.encode("utf-8"))
>>> f.close()

और कोडक "utf-8" का उपयोग करते हुए डेटा को डीकोड करें:

>>> data = open("/tmp/test").read()
>>> data.decode("utf-8")
u'bats\xe0'

और अगर आप इस स्ट्रिंग पर प्रिंट निष्पादित करने का प्रयास करते हैं, तो यह "utf-8" कोडेक्स का उपयोग करके स्वचालित रूप से डिकोड करेगा

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