क्यों popen.communicate () 'hi' के बजाय b'hi \ n 'लौटाता है?


95

क्या कोई समझा सकता है कि परिणाम मुझे क्यों चाहिए, "हाय", एक पत्र 'बी' से पहले और एक नई पंक्ति के साथ है?

मैं पायथन 3.3 का उपयोग कर रहा हूं

>>> import subprocess
>>> print(subprocess.Popen("echo hi", shell=True,
                           stdout=subprocess.PIPE).communicate()[0])
b'hi\n'

यह अतिरिक्त 'बी' प्रकट नहीं होता है अगर मैं इसे अजगर 2.7 के साथ चलाता हूं


1
आप पायथन के किस संस्करण का उपयोग कर रहे हैं?
नेक्रोलाइट 2

2
'बी' के बारे में निश्चित नहीं है, लेकिन न्यूलाइन है क्योंकि echo hiप्रिंट hi\r\n। उससे बचने के लिए, आप अंत में .strip () जोड़ सकते हैं, या इसी तरह का फिक्स कर सकते हैं।
अझरेई

7
आप यहाँ के check_output()बजाय उपयोग कर सकते हैं .communicate():print(subprocess.check_output("echo hi", shell=True, universal_newlines=True), end="")
jfs

जवाबों:


22

डिफ़ॉल्ट रूप से प्रतिध्वनि आदेश एक नया वर्ण देता है

इसके साथ तुलना करें:

print(subprocess.Popen("echo -n hi", \
    shell=True, stdout=subprocess.PIPE).communicate()[0])

के रूप में स्ट्रिंग पूर्ववर्ती यह इंगित करता है कि यह एक बाइट क्रम जो अजगर में एक सामान्य स्ट्रिंग के बराबर है है 2.6+

http://docs.python.org/3/reference/lexical_analysis.html#literals


6
आपको कोष्ठकों के अंदर '\' की जरूरत नहीं है।
JFS

95

bइंगित करता है कि क्या आपके पास है bytesजो एक द्विआधारी के बजाय यूनिकोड वर्ण की एक स्ट्रिंग बाइट्स के अनुक्रम है। सबप्रोसेस आउटपुट बाइट्स, अक्षर नहीं, इसलिए यह है कि क्या communicate()लौट रहा है।

bytesप्रकार सीधे नहीं है print()तो आप दिखाया जा रहा है कर रहे हैं, सक्षम reprकी bytesआप की है। यदि आपको पता है कि आपको उपप्रकार से प्राप्त बाइट्स की एन्कोडिंग है, तो आप decode()उन्हें एक मुद्रण योग्य में बदलने के लिए उपयोग कर सकते हैं str:

>>> print(b'hi\n'.decode('ascii'))
hi

बेशक, यह विशिष्ट उदाहरण केवल तभी काम करता है जब आप वास्तव में उपप्रकार से ASCII प्राप्त कर रहे हों। यदि यह ASCII नहीं है, तो आपको एक अपवाद मिलेगा:

>>> print(b'\xff'.decode('ascii'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0…

न्यूलाइन echo hiमें आउटपुट का हिस्सा है । echoनौकरी एक पैरामीटर है जिसे आप इसे पारित करते हैं, उसके बाद एक नई पंक्ति। यदि आप प्रक्रिया आउटपुट के आसपास व्हाट्सएप में रुचि नहीं रखते हैं, तो आप इसका उपयोग कर सकते हैं strip():

>>> b'hi\n'.strip()
b'hi'

1
आप एक पूर्ववर्ती 'बी' के बिना बाइट स्ट्रिंग प्रिंट करने के लिए प्रिंट () फ़ंक्शन कैसे प्राप्त करते हैं? या क्या आपको इसे पहले एक यूनिकोड स्ट्रिंग में बदलने की आवश्यकता है?
कल्पनाथ

मैं उत्सुक हूँ, जब os.popenपाठ के तार लौटाता हूं, तो subprocess.Popenबाइट के तार के बजाय उन्हें वापस करने का एक तरीका भी है।
पावेल Paमेरदा

11
मैं अपने आप को जवाब दूंगा, वहाँ एक गूढ़ नाम का विकल्प है, universal_newlinesजो Popenऑब्जेक्ट को टेक्स्ट स्ट्रिंग्स को स्वीकार करने और वापस करने का कारण बनता है ।
पावेल Paमरदा

3
@ Pavelenimerda जबकि os.popen पाठ स्ट्रिंग देता है, वे जाहिरा तौर पर गैर-एससीआई पात्रों के लिए गलत तरीके से डिकोड किए जा रहे हैं, कम से कम विंडोज पर। उदाहरण के लिए check_output("dir"), आउटपुट से फ़ाइल नाम निकालना और फिर openफ़ाइल नाम में जर्मन umlauts होने पर इसे एक्सेस करने की कोशिश करना विफल हो जाएगा। बग हो सकता है।
kdb

61

जैसा कि पहले उल्लेख किया गया है, echo hiवास्तव में वापसी करता है hi\n, जो कि एक अपेक्षित व्यवहार है।

लेकिन आप शायद डेटा को "सही" प्रारूप में प्राप्त करना चाहते हैं और एन्कोडिंग से निपटना नहीं चाहते हैं। आपको बस इतना universal_newlines=Trueकरने के लिए पास विकल्प चुनना होगा subprocess.Popen():

>>> import subprocess
>>> print(subprocess.Popen("echo hi",
                           shell=True,
                           stdout=subprocess.PIPE,
                           universal_newlines=True).communicate()[0])
hi

यह तरीका Popen()इन अवांछित प्रतीकों को खुद से बदल देगा।


11
universal_newlines=Trueएक जादू की तरह काम किया। मेरी विनम्र राय में, यह स्वीकृत उत्तर होना चाहिए ...
एथन स्ट्राइडर

3
यह अतिरिक्त खाली लाइनें पैदा करता है।
LoMaPh

1
आप की आवश्यकता हो सकती दोनों universal_newlines=True में Popen(से छुटकारा पाने के b'') और एक strip()परिणामस्वरूप स्ट्रिंग पर, यदि आप समाप्त न्यू लाइन काटना चाहते हैं।
arielf

FYI करें, दस्तावेज़ कहता universal_newlinesहै कि अब textपैरामीटर के लिए केवल एक पश्चगामी-संगत उपनाम है , जो स्पष्ट है लेकिन केवल पायथन 3.7 और इसके बाद के संस्करण में है।
हैरी कट्स

यह अतिरिक्त खाली लाइनों का उत्पादन करता है क्योंकि यह काम नहीं करता है।
Universal_newlines

8

b बाइट प्रतिनिधित्व है और \ n इको आउटपुट का परिणाम है।

निम्नलिखित केवल परिणाम डेटा मुद्रित करेगा

import subprocess
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip())
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.