python - একটি স্ট্রিং বাইট রূপান্তর?




string python-3.x (11)

আমি একটি বহিরাগত প্রোগ্রাম থেকে স্ট্যান্ডার্ড আউটপুট পেতে এই কোড ব্যবহার করছি:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]

যোগাযোগ () পদ্ধতি বাইটগুলির একটি অ্যারে প্রদান করে:

>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

যাইহোক, আমি আউটপুট দিয়ে স্বাভাবিক পাইথন স্ট্রিং হিসাবে কাজ করতে চাই। যাতে আমি এটি ভালো মুদ্রণ করতে পারে:

>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

আমি মনে করি binascii.b2a_qp() পদ্ধতিটি কী, কিন্তু যখন আমি এটি চেষ্টা করেছি, তখন আবার একই বাইট অ্যারে পেয়েছিলাম:

>>> binascii.b2a_qp(command_stdout)
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

যে কেউ বাইট মান ফিরে স্ট্রিং কিভাবে রূপান্তর করতে জানেন? আমি বলতে চাচ্ছি, এটি নিজে করার পরিবর্তে "ব্যাটারী" ব্যবহার করে। এবং আমি পাইথন 3 এর সাথে ঠিক করতে চাই।


আপনি একটি স্ট্রিং উত্পাদন করতে বাইট বস্তু ডিকোড করতে হবে:

>>> b"abcde"
b'abcde'

# utf-8 is used here because it is a very common encoding, but you
# need to use the encoding your data is actually in.
>>> b"abcde".decode("utf-8") 
'abcde'

আপনি বাইট স্ট্রিং ডিকোড এবং এটি একটি চরিত্র (ইউনিকোড) স্ট্রিং চালু করতে হবে।

b'hello'.decode(encoding)

অথবা

str(b'hello', encoding)

আমি আসলে আপনি চান কি মনে হয়:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')

হারুনের উত্তরটি সঠিক ছিল, এটি ব্যতীত আপনাকে কী কী এনকোডিং ব্যবহার করতে হবে তা জানা প্রয়োজন। এবং আমি বিশ্বাস করি যে উইন্ডোজগুলি 'উইন্ডোজ -1252' ব্যবহার করে। আপনার বিষয়বস্তুতে আপনার কিছু অস্বাভাবিক (অ-অ্যাসিসি) অক্ষর থাকলে এটি কেবলমাত্র ব্যাপার হবে তবে এটি একটি পার্থক্য তৈরি করবে।

যাইহোক, এটি কোনও ব্যাপার নয় যে পাইথন বাইনারি এবং পাঠ্য তথ্যের জন্য দুটি ভিন্ন ধরণের ব্যবহার করার জন্য সরানো হয়েছে: এটি তাদের মধ্যে যাদুকর রূপান্তর করতে পারে না কারণ এটি যদি না জানায় তবে এটি এনকোডিংটি জানেন না! উইন্ডোজ ডকুমেন্টেশনটি পড়ার একমাত্র উপায় হল (অথবা এটি এখানে পড়ুন)।


আমি এই ভাবে সহজ মনে করি:

bytes = [112, 52, 52]
"".join(map(chr, bytes))
>> p44

উইন্ডোজ সিস্টেম থেকে তথ্য নিয়ে কাজ করার সময় ( \r\n লাইন শেষের সাথে), আমার উত্তরটি হল

String = Bytes.decode("utf-8").replace("\r\n", "\n")

কেন? একটি multiline ইনপুট.txt দিয়ে এটি ব্যবহার করে দেখুন:

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8")
open("Output.txt", "w").write(String)

আপনার সমস্ত লাইন শেষ দ্বিগুণ হবে ( \r\r\n ), যা অতিরিক্ত ফাঁকা লাইনের দিকে অগ্রসর হবে। পাইথনের পাঠ্য-পাঠ্য ফাংশনগুলি সাধারণত লাইনের শেষগুলি স্বাভাবিক করে যাতে স্ট্রিংগুলি কেবলমাত্র \n ব্যবহার করে। আপনি উইন্ডোজ সিস্টেম থেকে বাইনারি তথ্য পাবেন, পাইথন এটি করার সুযোগ নেই। সুতরাং,

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8").replace("\r\n", "\n")
open("Output.txt", "w").write(String)

আপনার মূল ফাইল প্রতিলিপি হবে।


একটি পাঠ্য হিসাবে একটি বাইট ক্রম ব্যাখ্যা করার জন্য, আপনি সংশ্লিষ্ট অক্ষর এনকোডিং জানতে হবে:

unicode_text = bytestring.decode(character_encoding)

উদাহরণ:

>>> b'\xc2\xb5'.decode('utf-8')
'µ'

ls কমান্ড টেক্সট হিসাবে ব্যাখ্যা করা যাবে না আউটপুট উত্পাদন করতে পারে। স্ল্যাশ b'/' এবং শূন্য b'\0' ব্যতীত ইউনিক্সের ফাইল নাম বাইটের কোনও ক্রম হতে পারে:

>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()

ইউটিএফ -8 এনকোডিং ব্যবহার করে যেমন বাইট স্যুপ ডিকোড করার চেষ্টা করছে UnicodeDecodeError

এটা খারাপ হতে পারে। ডিকোডিং mojibake ব্যর্থ হতে পারে এবং আপনি যদি ভুল অসঙ্গতিপূর্ণ এনকোডিং ব্যবহার করেন তবে mojibake তৈরি করুন:

>>> '—'.encode('utf-8').decode('cp1252')
'—'

তথ্য দূষিত কিন্তু আপনার প্রোগ্রাম অবশেষ যে একটি ব্যর্থতা অবশেষ অবশেষ।

সাধারণভাবে, কোন চরিত্র এনকোডিং ব্যবহার করতে হয় বাইট ক্রম নিজেই এম্বেড করা হয় না। আপনি এই তথ্য আউট অফ ব্যান্ড যোগাযোগ করতে হবে। কিছু ফলাফল অন্যদের চেয়ে বেশি সম্ভাবনাময় এবং তাই chardet মডিউল বিদ্যমান যা অক্ষর এনকোডিং অনুমান করতে পারে । একটি একক পাইথন স্ক্রিপ্ট বিভিন্ন স্থানে একাধিক চরিত্র এনকোডিং ব্যবহার করতে পারে।

os.fsdecode() ফাংশন ব্যবহার করে ls আউটপুটটি একটি পাইথন স্ট্রিং রূপান্তর করা যেতে পারে যা অব্যবহৃত ফাইলের নামগুলির জন্যও সফল হয় (এটি sys.getfilesystemencoding() এবং ইউনিক্সে sys.getfilesystemencoding() ত্রুটি হ্যান্ডলার ব্যবহার করে):

import os
import subprocess

output = os.fsdecode(subprocess.check_output('ls'))

মূল বাইট পেতে, আপনি os.fsencode() ব্যবহার করতে পারেন।

যদি আপনি universal_newlines=True পরামিতিটি পাস করেন তবে subprocess locale.getpreferredencoding(False) ব্যবহার করে বাইট ডিকোড করতে যেমন, এটি উইন্ডোজ cp1252 হতে পারে।

বাইট স্ট্রিম অন-ফ্লাই ডিকোড করার জন্য, io.TextIOWrapper() ব্যবহার করা যেতে পারে: example ।

বিভিন্ন কমান্ড তাদের আউটপুটের জন্য বিভিন্ন চরিত্র এনকোডিং ব্যবহার করতে পারে যেমন, dir অভ্যন্তরীণ কমান্ড ( cmd ) cp437 ব্যবহার করতে পারে। এর আউটপুট ডিকোড করার জন্য, আপনি এনকোডিংটি স্পষ্টভাবে পাস করতে পারেন (পাইথন 3.6+):

output = subprocess.check_output('dir', shell=True, encoding='cp437')

ফাইল নামগুলি os.listdir() থেকে পৃথক হতে পারে (যা উইন্ডোজ ইউনিকোড API ব্যবহার করে) উদাহরণস্বরূপ, '\xb6' '\x14' পপথন এর সিপি 437 কোডেক মানচিত্র b'\x14' দিয়ে প্রতিস্থাপিত হতে পারে অক্ষর U + 0014 এর পরিবর্তে U + 0014 কে নিয়ন্ত্রণ করতে। + 00 বি 6 (¶)। ইচ্ছাকৃত ইউনিকোড অক্ষরগুলির সাথে ফাইল নাম সমর্থন করার জন্য, ডিকোড পাউসেল আউটপুটটি সম্ভবত একটি পাইথন স্ট্রিংয়ের মধ্যে অ-অ্যাসিসি ইউনিকোড অক্ষর ধারণ করে দেখুন


যদি আপনি এনকোডিংটি না জানেন তবে পাইথন 3 এবং পাইথন 2 সামঞ্জস্যপূর্ণ ভাবে স্ট্রিংয়ে বাইনারি ইনপুট পড়তে প্রাচীন এমএস-ডস cp437 এনকোডিং ব্যবহার করুন:

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('cp437'))

কারণ এনকোডিং অজানা, cp437 অক্ষরগুলিতে অনুবাদ করতে অ-ইংরাজী প্রতীকগুলি cp437 (ইংরেজী অক্ষর অনুবাদ করা হয় না, কারণ তারা বেশিরভাগ বাইট এনকোডিং এবং UTF-8 তে মিলিত হয়)।

UTF-8 এ নির্বিচারে বাইনারি ইনপুট ডিকোডিং অনিরাপদ, কারণ আপনি এটি পেতে পারেন:

>>> b'\x00\x01\xffsd'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid
start byte

একইটি পাইথন 2-এর জন্য জনপ্রিয় (ডিফল্ট?) প্রযোজ্য। কোডপ্যাড লেআউটে অনুপস্থিত বিন্দুগুলি দেখুন - এটিই যেখানে পাইথন কুখ্যাত ordinal not in range সাথে ordinal not in range

20150604 আপডেট করুন : পাইথন 3 এর তথ্য হ্রাস এবং ক্র্যাশ ছাড়াই বাইনারি তথ্যগুলিতে এনকোডিং স্টাফের জন্য স্ট্রোগেটেসস্কেপ ত্রুটি কৌশল আছে তবে এটি কার্য সম্পাদন এবং নির্ভরযোগ্যতা যাচাই করতে রূপান্তর পরীক্ষা [binary] -> [str] -> [binary] প্রয়োজন।

20170116 আপডেট করুন : Nearoo দ্বারা মন্তব্য করার জন্য ধন্যবাদ - backslashreplace ত্রুটি হ্যান্ডলার সহ সমস্ত অজানা বাইটগুলি পাল্টানোর সম্ভাবনা রয়েছে। এটি শুধুমাত্র পাইথন 3 এর জন্য কাজ করে, তাই এই কাজের সাথে আপনি এখনও বিভিন্ন পাইথন সংস্করণগুলির থেকে অসঙ্গতিপূর্ণ আউটপুট পাবেন:

PY3K = sys.version_info >= (3, 0)

lines = []
for line in stream:
    if not PY3K:
        lines.append(line)
    else:
        lines.append(line.decode('utf-8', 'backslashreplace'))

বিস্তারিত জানার জন্য https://docs.python.org/3/howto/unicode.html#python-s-unicode-support দেখুন।

20170119 আপডেট করুন : আমি পাইথন 2 এবং পাইথন 3 উভয়ের জন্য স্ল্যাশ এড়িয়ে যাওয়া ডিস্কো বাস্তবায়ন করার সিদ্ধান্ত নিয়েছি। এটি cp437 সমাধানটি ধীরে ধীরে হওয়া উচিত, তবে এটি প্রতিটি পাইথন সংস্করণে একই ফলাফল তৈরি করা উচিত।

# --- preparation

import codecs

def slashescape(err):
    """ codecs error handler. err is UnicodeDecode instance. return
    a tuple with a replacement for the unencodable part of the input
    and a position where encoding should continue"""
    #print err, dir(err), err.start, err.end, err.object[:err.start]
    thebyte = err.object[err.start:err.end]
    repl = u'\\x'+hex(ord(thebyte))[2:]
    return (repl, err.end)

codecs.register_error('slashescape', slashescape)

# --- processing

stream = [b'\x80abc']

lines = []
for line in stream:
    lines.append(line.decode('utf-8', 'slashescape'))

যেহেতু এই প্রশ্নটি আসলে subprocess আউটপুট সম্পর্কে জিজ্ঞাসা করা হচ্ছে, তাই আপনার কাছে আরও সরাসরি পদ্ধতি রয়েছে কারণ Popen একটি encoding কীওয়ার্ড গ্রহণ করে (পাইথন 3.6+ এ):

>>> from subprocess import Popen, PIPE
>>> text = Popen(['ls', '-l'], stdout=PIPE, encoding='utf-8').communicate()[0]
>>> type(text)
str
>>> print(text)
total 0
-rw-r--r-- 1 wim badger 0 May 31 12:45 some_file.txt

অন্যান্য ব্যবহারকারীদের জন্য সাধারণ উত্তর টেক্সটগুলিতে বাইট ডিকোড করতে হয়:

>>> b'abcde'.decode()
'abcde'

কোন যুক্তি ছাড়াই, sys.getdefaultencoding() ব্যবহার করা হবে। যদি আপনার তথ্য sys.getdefaultencoding() না sys.getdefaultencoding() তবে আপনি অবশ্যই sys.getdefaultencoding() এনকোডিং নির্দিষ্টভাবে উল্লেখ করতে হবে:

>>> b'caf\xe9'.decode('cp1250')
'café'

http://docs.python.org/3/library/sys.html থেকে,

স্ট্যান্ডার্ড স্ট্রিম থেকে বাইনারি ডেটা লিখতে বা পড়তে, অন্তর্নিহিত বাইনারি বাফারটি ব্যবহার করুন। উদাহরণস্বরূপ, stdout এ বাইট লেখার জন্য, sys.stdout.buffer.write (b'abc ') ব্যবহার করুন।


পাইথন 3 এ , ডিফল্ট এনকোডিং "utf-8" , তাই আপনি সরাসরি ব্যবহার করতে পারেন:

b'hello'.decode()

যা সমতুল্য

b'hello'.decode(encoding="utf-8")

অন্যদিকে, পাইথন 2 এ , এনকোডিং ডিফল্ট স্ট্রিং এনকোডিংয়ের ডিফল্ট। সুতরাং, আপনি ব্যবহার করা উচিত:

b'hello'.decode(encoding)

encoding যেখানে আপনি encoding হয়।

দ্রষ্টব্য: কীওয়ার্ড আর্গুমেন্টগুলির জন্য সমর্থন পাইথন 2.7 এ যোগ করা হয়েছে।


def toString(string):    
    try:
        return v.decode("utf-8")
    except ValueError:
        return string

b = b'97.080.500'
s = '97.080.500'
print(toString(b))
print(toString(s))




python-3.x