বাইটগুলি স্ট্রিংয়ে রূপান্তর করুন


2299

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

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

আমি ভেবেছিলাম যে বিনাসি.ইবি 2 এ_কিপি () পদ্ধতিটি এর জন্য, তবে যখন আমি এটি চেষ্টা করেছি তখন আবার একই বাইট অ্যারে পেয়েছি:

>>> 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 এর সাথে ঠিক আছে তা চাই।


46
কেন str(text_bytes)কাজ করে না ? এটি আমার কাছে উদ্ভট বলে মনে হচ্ছে।
চার্লি পার্কার

12
@ CharlieParker কারণ str(text_bytes)এনকোডিং নির্দিষ্ট করতে পারে না। টেক্সট_বাইটে কী রয়েছে তার উপর নির্ভর করে text_bytes.decode('cp1250) `এর ফলে খুব আলাদা স্ট্রিং হতে পারে text_bytes.decode('utf-8')
ক্রেগ অ্যান্ডারসন

6
সুতরাং strফাংশন একটি বাস্তব স্ট্রিং রূপান্তর করে না। একজন কোনও কারণে কোনও এনকোডিং স্পষ্টভাবে বলতে চাইছেন কেন আমি তা পড়তে অলস হই। কেবল এটিকে রূপান্তর করুন utf-8এবং দেখুন আপনার কোডটি কাজ করে কিনা। উদাহরণস্বরূপvar = var.decode('utf-8')
চার্লি পার্কার

@CraigAnderson: unicode_text = str(bytestring, character_encoding)কাজ পাইথন 3. যদিও উপর আশানুরূপ unicode_text = bytestring.decode(character_encoding)শুধু -এর সঙ্গে গুলিয়ে না আরো বাঞ্ছনীয় str(bytes_obj)যে জন্য একটি টেক্সট প্রতিনিধিত্ব উৎপন্ন bytes_objপাঠ্যে এটি ডিকোডিং পরিবর্তে: str(b'\xb6', 'cp1252') == b'\xb6'.decode('cp1252') == '¶'এবংstr(b'\xb6') == "b'\\xb6'" == repr(b'\xb6') != '¶'
JFS

উত্তর:


3669

স্ট্রিং তৈরি করতে আপনার বাইটস অবজেক্টটি ডিকোড করতে হবে:

>>> 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'

57
ব্যবহার "windows-1252"করা কোনওভাবেই নির্ভরযোগ্য নয় (যেমন উইন্ডোজের অন্যান্য ভাষার সংস্করণগুলির জন্য), এটি ব্যবহার করা ভাল না sys.stdout.encoding?
নিকো 15

12
হতে পারে এটি কাউকে আরও সাহায্য করবে: কখনও কখনও আপনি প্রাক্তন টিসিপি যোগাযোগের জন্য বাইট অ্যারে ব্যবহার করেন। আপনি যদি '\ x00' অক্ষরগুলি অনুসরণ করে স্ট্রিং কে বাইট অ্যারে রূপান্তর করতে চান তবে নিম্নলিখিত উত্তরটি যথেষ্ট নয়। বি'সাম্পল \ x00 \ x00'.decode ('utf-8') ব্যবহার করুন then স্ট্রিপ ('\ x00') তারপরে।
Wookie88

2
আমি এটি bugs.python.org/issue17860 এ নথিভুক্ত সম্পর্কে একটি বাগ পূরণ করেছি - কোনও প্যাচ প্রস্তাব দিতে নির্দ্বিধায়। যদি এতে অবদান রাখা শক্ত হয় - কীভাবে উন্নতি করতে হবে তা মন্তব্য স্বাগত।
অ্যানাটোলি টেকটোনিক

44
পাইথনে ২.7..6 হ্যান্ডেল করে না b"\x80\x02\x03".decode("utf-8")-> UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte
মার্টিনিউ

9
যদি সামগ্রীটি এলোমেলোভাবে বাইনারি মান হয় তবে utf-8রূপান্তরটি ব্যর্থ হওয়ার সম্ভাবনা রয়েছে। এর পরিবর্তে (নীচে) @techtonik উত্তর দেখার stackoverflow.com/a/27527728/198536
wallyk

214

আপনাকে বাইট স্ট্রিংটি ডিকোড করতে হবে এবং এটিকে একটি অক্ষর (ইউনিকোড) স্ট্রিংয়ে পরিণত করতে হবে।

পাইথন 2 এ

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

অথবা

unicode('hello', encoding)

পাইথন 3 এ

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

অথবা

str(b'hello', encoding)

2
পাইথন 3-এ, স্ট্রিংটি যদি একটি চলকতে থাকে?
আলা এম।

1
@ আলাআম .: একই। যদি আপনার কাছে থাকে variable = b'hello'তবেunicode_text = variable.decode(character_encoding)
jfs

182

আমি মনে করি এই উপায়টি সহজ:

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

6
আপনাকে ধন্যবাদ, আপনার পদ্ধতিটি আমার পক্ষে কাজ করেছিল যখন অন্য কেউ না করে। আমার একটি নন-এনকোডেড বাইট অ্যারে ছিল যা আমার স্ট্রিংয়ে পরিণত হয়েছিল। এটি পুনরায় এনকোড করার কোনও উপায় অনুসন্ধান করার চেষ্টা করছিল যাতে আমি এটিকে একটি স্ট্রিংয়ে ডিকোড করতে পারি। এই পদ্ধতিটি পুরোপুরি কাজ করে!
লেটনাটশেড

5
@ লিটনাইটশেড: তবু এটি মারাত্মকভাবে অক্ষম। আপনার যদি বাইট অ্যারে থাকে তবে আপনার কেবল ডিকোডিং করতে হবে।
মার্টিজন পিটারস

12
@Martijn Pieters আমি শুধু এই অন্যান্য উত্তরের সঙ্গে একটি সহজ বেঞ্চমার্ক করেনি, একাধিক 10,000 রান চলমান stackoverflow.com/a/3646405/353094 আর উপরে সমাধান আসলে অনেক দ্রুত প্রতি একক সময় ছিল। পাইথন ২.7..7 এ 10,000 রানের জন্য এটি 8 এমএস লাগে, অন্যদের তুলনায় 12 মিমি এবং 18 এমএসে। অনুমোদিত যে ইনপুট, পাইথন সংস্করণ ইত্যাদির উপর নির্ভর করে কিছু ভিন্নতা থাকতে পারে আমার পক্ষে খুব ধীর বলে মনে হয় না।
leetNightshade

5
@ মার্তিজান পিটারস হ্যাঁ সুতরাং এই দফার সাথে, এটি জিজ্ঞাসা করা প্রশ্নটির শরীরের পক্ষে সেরা উত্তর নয়। এবং শিরোনাম বিভ্রান্তিকর, তাই না? তিনি / বাইট স্ট্রিংটি একটি স্ট্রিংতে বাইট অ্যারে নয়, একটি নিয়মিত স্ট্রিংয়ে রূপান্তর করতে চান। এই উত্তরটি জিজ্ঞাসা করা শিরোনামের জন্য ঠিক আছে।
leetNightshade

5
অজগর 3 এর সমান হতে হবে bytes([112, 52, 52])- বিটিডাব্লু বাইটস স্থানীয় ভেরিয়েবলের খারাপ নাম হ'ল কারণ এটি একটি পি
বিল্টিন

91

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

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

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

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

ইউটিএফ -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

এটি একই ক্ষেত্রে প্রযোজ্য latin-1, যা পাইথন ২ এর জন্য জনপ্রিয় (ডিফল্ট?) ছিল C কোডপেজ লেআউটে অনুপস্থিত পয়েন্টগুলি দেখুন - এটিই যেখানে পাইথন কুখ্যাতদের সাথে দম বন্ধ হয়ে গেছে ordinal not in range

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

আপডেট 20170116 : নিকোয়ারের মন্তব্যের জন্য ধন্যবাদ - 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'))

দেখুন পাইথন ইউনিকোড সাপোর্ট বিস্তারিত জানার জন্য।

আপডেট 20170119 : আমি পাইথন 2 এবং পাইথন 3 উভয়ের জন্য কাজ করে এমন স্ল্যাশ এস্কেপিং ডিকোড বাস্তবায়নের সিদ্ধান্ত নিয়েছি It এটি 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'))

6
আমি সত্যই মনে করি পাইথনের নিখোঁজ প্রতীকগুলি প্রতিস্থাপন এবং চালিয়ে যাওয়ার জন্য একটি ব্যবস্থা সরবরাহ করা উচিত।
অ্যানাটোলি টেকটোনিক

2
উজ্জ্বল! এটি 256 এমবি ফাইলের জন্য @ সিসোর পদ্ধতির চেয়ে অনেক দ্রুত!
wallyk

@ টেকটোনিক: পাইথন 2-তে এটি যেমন কাজ করেছে তেমন কোনও অ্যারেতে কাজ করবে না।
ব্যবহারকারী 2284570

@ ব্যবহারকারী 2284570 আপনি তালিকাটি বোঝাতে চান? এবং এটি অ্যারেতে কাজ করা উচিত কেন? বিশেষত
ভাসমানদের

3
@ অ্যানাটোলিটেকটোনিক স্ট্রিংয়ের মধ্যে পালানোর ক্রম ছেড়ে যাওয়ার এবং এগিয়ে যাওয়ার সম্ভাবনা রয়েছে: b'\x80abc'.decode("utf-8", "backslashreplace")ফলস্বরূপ হবে '\\x80abc'। এই তথ্যটি ইউনিকোড ডকুমেন্টেশন পৃষ্ঠা থেকে নেওয়া হয়েছিল যা মনে হয় এই উত্তরটি লেখার পরে আপডেট হয়েছিল।
Nearoo

86

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

b'hello'.decode()

যা সমান

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

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

b'hello'.decode(encoding)

encodingআপনি যে এনকোডিংটি চান তা কোথায়

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


41

আমি মনে করি আপনি আসলে এটি চান:

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

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

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


3
open()পাঠ্য স্ট্রিমগুলির জন্য কাজ করুন বা Popen()আপনি যদি এটি পাস করেন তবে universal_newlines=Trueআপনার জন্য চরিত্রের এনকোডিংটি locale.getpreferredencoding(False)যাদুতে সিদ্ধান্ত নেবে ( পাইথন ৩.৩+ এ)।
jfs

2
'latin-1'সমস্ত কোড পয়েন্ট সেট সহ একটি ভারব্যাটিম এনকোডিং, সুতরাং আপনি যে পাইথন সমর্থন করে যে কোনও ধরণের স্ট্রিংয়ের মধ্যে একটি বাইট স্ট্রিং কার্যকরভাবে পড়তে ব্যবহার করতে পারেন (তাই পাইথন 2 এ ভার্চ্যাটিম, পাইথন 3 এর ইউনিকোডে)।
ট্রিপলি

@ ট্রিপলি: মোজিবাকে 'latin-1'পাওয়ার ভাল উপায়। উইন্ডোজে dir\xb6\x14
magন্দ্রজালিক

32

সর্বজনীন_ নিউলাইনসকে সত্য হিসাবে সেট করুন

command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]

5
আমি এই পদ্ধতিটি ব্যবহার করছি এবং এটি কার্যকর হয় works যদিও এটি আপনার সিস্টেমে ব্যবহারকারীর পছন্দসই ভিত্তিতে এনকোডিংয়ের বিষয়ে অনুমান করছে, তাই এটি অন্যান্য কয়েকটি বিকল্পের মতো শক্তিশালী নয়। এটি যা করছে, ডকস.পিথন.আর.পিথন.আর.৩.৪ / লিবারি / সাউবপ্রসেসিএইচটিএমএলকে উল্লেখ করে: "যদি সর্বজনীন_নিয়লাইনগুলি সত্য হয়, তবে [স্ট্যান্ডিন, স্টাডআউট এবং স্টডার] স্থানীয় দ্বারা প্রত্যাবর্তিত এনকোডিংটি ব্যবহার করে সর্বজনীন নিউলাইনস মোডে পাঠ্য স্ট্রিম হিসাবে খোলা হবে .getpreferredencoding (মিথ্যা)। "
twasbrillig

3.7 এ আপনি এর text=Trueপরিবর্তে (এবং করা উচিত) করতে পারেন universal_newlines=True
বরিস

23

যদিও @Aaron Maenpaa এর উত্তর ঠিকঠাক কাজ করছে, একটি ব্যবহারকারী সম্প্রতি জিজ্ঞাসা :

আর কোন সহজ উপায় আছে? 'fhand.read ()। ডিকোড ("ASCII")' [...] এত দীর্ঘ!

তুমি ব্যবহার করতে পার:

command_stdout.decode()

decode()একটি স্ট্যান্ডার্ড যুক্তি আছে :

codecs.decode(obj, encoding='utf-8', errors='strict')


.decode()যে ব্যবহারগুলি 'utf-8'ব্যর্থ হতে পারে (কমান্ডের আউটপুট একটি পৃথক অক্ষর এনকোডিং ব্যবহার করতে পারে বা এমনকি একটি অনির্বচনীয় বাইট অনুক্রম ফিরে আসতে পারে)। যদিও ইনপুটটি ascii হয় (utf-8 এর একটি উপসেট) তবে .decode()কাজ করে।
jfs

22

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

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

Utf-8 এনকোডিং ব্যবহার করে এই জাতীয় বাইট স্যুপটি ডিকোড করার চেষ্টা করা হচ্ছে UnicodeDecodeError

এটা আরও খারাপ হতে পারে। ডিকোডিংটি নিঃশব্দে ব্যর্থ হতে পারে এবং যদি আপনি একটি ভুল বেমানান এনকোডিং ব্যবহার করেন তবে মোজিবাকে উত্পাদন করতে পারে :

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

ডেটা দূষিত হয়েছে তবে আপনার প্রোগ্রামটি অসচেতন রয়ে গেছে যে কোনও ব্যর্থতা ঘটেছে।

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


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

import os
import subprocess

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

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

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

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

বিভিন্ন কমান্ড তাদের আউটপুটের জন্য পৃথক অক্ষর এনকোডিংগুলি ব্যবহার করতে পারে যেমন dirঅভ্যন্তরীণ কমান্ড ( cmd) সিপি 437 ব্যবহার করতে পারে। এর আউটপুটটি ডিকোড করার জন্য আপনি স্পষ্টভাবে এনকোডিংটি পাস করতে পারেন (পাইথন ৩.6++):

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

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


16

যেহেতু এই প্রশ্নটি আসলে subprocessআউটপুট সম্পর্কে জিজ্ঞাসা করছে , আপনার Popenএকটি এনকোডিং কীওয়ার্ড গ্রহণ করার পরে আপনার কাছে আরও সরাসরি পদ্ধতির উপস্থিতি রয়েছে (পাইথন ৩.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(), তবে আপনাকে অবশ্যই অবশ্যই decodeকলটিতে এনকোডিং নির্দিষ্ট করতে হবে :

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

3
অথবা পাইথন ৩.7 এর সাহায্যে আপনি text=Trueপ্রদত্ত এনকোডিং (যদি সেট থাকে) অথবা অন্যথায় সিস্টেমের ডিফল্ট ব্যবহার করে স্টিডিন, স্টডআউট এবং স্ট্ডারকে ডিকোড করতে পারবেন । Popen(['ls', '-l'], stdout=PIPE, text=True)
বোরিস

এনকোডিং lsব্যবহার করে ডিকোডিং আউটপুট utf-8ব্যর্থ হতে পারে ( ২০১ answer সালের উত্তরটির উদাহরণ দেখুন )।
jfs

1
@ বরিস: যদি encodingপ্যারামিটার দেওয়া হয় তবে textপ্যারামিটারটি এড়ানো হবে।
jfs

11

আপনার চেষ্টা করে নিম্নলিখিতগুলি পাওয়া উচিত decode():

AttributeError: 'str' অবজেক্টটির কোনও 'ডিকোড' নেই

আপনি সরাসরি একটি কাস্টে এনকোডিং প্রকারটি নির্দিষ্ট করতে পারেন:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'

6

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

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

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

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)

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


আমি .replace("\r\n", "\n")এতক্ষণ সংযোজন খুঁজছিলাম আপনি যদি সঠিকভাবে এইচটিএমএল রেন্ডার করতে চান তবে এটি উত্তর।
mhlavacka

5

আমি একটি তালিকা পরিষ্কার করার জন্য একটি ফাংশন করেছি

def cleanLists(self, lista):
    lista = [x.strip() for x in lista]
    lista = [x.replace('\n', '') for x in lista]
    lista = [x.replace('\b', '') for x in lista]
    lista = [x.encode('utf8') for x in lista]
    lista = [x.decode('utf8') for x in lista]

    return lista

6
আপনি আসলে সব চেইন করতে .strip, .replace, .encodeএবং এক তালিকা ধী মধ্যে, ইত্যাদি কল শুধুমাত্র বারবার তালিকা ধরে একবার পরিবর্তে iterating এর উপর পাঁচবার।
টেলর এডমিস্টন

1
@ টেলরএডমিস্টন সম্ভবত এটি বরাদ্দ বাঁচাতে পারে তবে ক্রিয়াকলাপের সংখ্যা একই থাকবে।
জুলিয়ানড

5

পাইথন 3 জন্য, এই অনেক নিরাপদ এবং Pythonic পদ্ধতির থেকে রূপান্তর করতে byteকরতে string:

def byte_to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes): # Check if it's in bytes
        print(bytes_or_str.decode('utf-8'))
    else:
        print("Object not of byte type")

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

আউটপুট:

total 0
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

5
1) @ বোডাঙ্গলি বলেছিলেন, টাইপ চেকিং মোটেই পাইথোনিক নয়। 2) আপনি যে ফাংশনটি লিখেছেন তার নাম " byte_to_str" দেওয়া হয়েছে যা বোঝায় এটি একটি স্ট্রিং ফিরিয়ে দেবে, তবে এটি কেবল রূপান্তরিত মানটি মুদ্রণ করে এবং এটি ব্যর্থ হলে এটি একটি ত্রুটি বার্তা প্রিন্ট করে (তবে একটি ব্যতিক্রম বাড়াবে না)। এই পদ্ধতিরটিও অযৌক্তিক এবং bytes.decodeআপনার সরবরাহিত সমাধানটিকে বিস্মৃত করে ।
মহাজাগতিক ফ্লুক

3

সিস্টেম থেকে - সিস্টেম-নির্দিষ্ট পরামিতি এবং ফাংশন :

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


3
সাবপ্রসেসের পাইপটি ইতিমধ্যে বাইনারি বাফার। আপনার উত্তরটি ফলস্বরূপ bytesমান থেকে স্ট্রিং মান কীভাবে পাবেন তা সম্বোধন করতে ব্যর্থ ।
মার্টিজন পিটারস

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

1
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কীভাবে এবং / বা কেন এটি সমস্যার সমাধান করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করলে উত্তরের দীর্ঘমেয়াদী মান উন্নত হবে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, কেবল এখনই জিজ্ঞাসা করা ব্যক্তি নয়! একটি ব্যাখ্যা যুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন এবং কোন সীমাবদ্ধতা এবং অনুমানগুলি প্রযোজ্য তা একটি ইঙ্গিত দিন। এই উত্তরটি কেন অন্যদের চেয়ে বেশি উপযুক্ত তা উল্লেখ করেও ক্ষতি করে না।
দেব-আইএল

একটি ব্যাখ্যা ক্রম হবে।
পিটার মর্টেনসেন

1

পাইথন ৩.7-তে "শেল কমান্ড চালান এবং এর আউটপুট বাইটের পরিবর্তে পাঠ্য হিসাবে পান" এর ক্ষেত্রে আপনার নির্দিষ্ট ক্ষেত্রে, আপনার ব্যবহার subprocess.runও পাস করতে হবে text=True(পাশাপাশি capture_output=Trueআউটপুট ক্যাপচার করতে)

command_result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
command_result.stdout  # is a `str` containing your program's stdout

textবলা হত universal_newlines, এবং পাইথন ৩.7-এ পরিবর্তিত হয়েছিল (ভাল, এলিয়াসে)। আপনি যদি 3.7 এর আগে পাইথন সংস্করণ সমর্থন করতে চান তবে এর universal_newlines=Trueপরিবর্তে পাস করুন passtext=True


0

আপনি যদি কোনও বাইট রূপান্তর করতে চান তবে স্ট্রিংকে কেবল বাইটে রূপান্তরিত করতে হবে না:

with open("bytesfile", "rb") as infile:
    str = base64.b85encode(imageFile.read())

with open("bytesfile", "rb") as infile:
    str2 = json.dumps(list(infile.read()))

তবে এটি খুব দক্ষ নয়। এটি একটি 2 এমবি ছবি 9 এমবিতে রূপান্তরিত করবে।


আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.