2013-03-12 6 views
30

Qualcuno può spiegare perché il risultato che voglio, "ciao", è preceduto da una lettera "b" e seguito da una nuova riga?Perché Popen.communicate() restituisce b'hi n 'invece di' ciao '?

Sto usando Python 3,3

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

Questo 'b' in più non appare se l'eseguo con Python 2.7

+0

Quale versione di Python stai usando? – Necrolyte2

+0

Utilizzo della versione 3.3 – imagineerThat

+2

Non sono sicuro della 'b', ma la nuova linea è perché 'echo hi' stampa' hi \ r \ n'. Per evitare ciò, è possibile aggiungere .strip() alla fine o una soluzione simile. – azhrei

risposta

4

Il comando echo di default restituisce un carattere di nuova riga

Confronta con questo:

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

Come per il b precede la stringa indica che si tratta di una sequenza di byte che viene equivilent ad una normale stringa in Python 2.6+

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

+2

tu don ' t necessario '\' tra parentesi. – jfs

44

Il b indica che quello che hai è bytes, che è una sequenza binaria di byte anziché una stringa di caratteri Unicode. I sottoprocessi restituiscono i byte, non i caratteri, ecco cosa restituisce communicate().

Il tipo bytes non è direttamente print() in grado, quindi sei stato mostrato il repr del bytes che avete. Se si conosce la codifica del byte che hai ricevuto dal sottoprocesso, è possibile utilizzare decode() per convertirli in un stampabile str:

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

Naturalmente, questo esempio specifico funziona solo se effettivamente si ricevono ASCII dal sottoprocesso . Se non è ASCII, si otterrà un'eccezione:

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

La nuova linea è parte di ciò che ha echo hi uscita. Il lavoro di echo è quello di emettere i parametri che si passa, seguito da una nuova riga. Se non siete interessati a spazi che lo circondano l'uscita di processo, è possibile utilizzare strip() in questo modo:

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

Come si ottiene la funzione print() per stampare una stringa di byte senza una "b" precedente? O devi prima convertirlo in una stringa unicode? – imagineerThat

+0

Sì; vedi la mia modifica. Ma considera anche i pericoli della decodifica. – zigg

+0

Sono curioso, quando 'os.popen' restituisce stringhe di testo, anche se c'è un modo per rendere 'subprocess.Popen' anche restituirle, invece delle stringhe di byte. –

2

B è la rappresentazione di byte e \ n è il risultato della produzione eco.

segue stampa solo i dati dei risultati

import subprocess 
print(subprocess.Popen("echo hi", shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8').strip()) 
0

come accennato prima, echo hi in realtà fa ritorno hi\n, che si tratta di un comportamento previsto.

Ma probabilmente si desidera semplicemente ottenere i dati in un formato "giusto" e non gestire la codifica. Tutto quello che dovete fare è passare universal_newlines=True opzione per subprocess.Popen() in questo modo:

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

In questo modo Popen() sostituirà questi simboli indesiderati da sola.