2016-01-11 42 views
8

Mam skrypt Pythona, który używa podprocesu.Popen do wykonywania plików * .exe systemu Windows. Wszystkie EXE z wyjątkiem jednego dają oczekiwaną wydajność. Po wydrukowaniu za pomocą polecenia print() dane wyjściowe zawierają spacje między wszystkimi znakami wyjściowymi.Podproces Python wprowadza spacje

ten sposób wyjście wygląda podczas wykonywania EXE w wierszu poleceń Windows:

C:\Python27>autorunsc.exe /accepteula 

Sysinternals Autoruns v13.51 - Autostart program viewer 
Copyright (C) 2002-2015 Mark Russinovich 
Sysinternals - www.sysinternals.com 


HKLM\System\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\StartupPrograms 
    rdpclip 
    rdpclip 
    RDP Clip Monitor 
    Microsoft Corporation 
    6.1.7601.17514 
    c:\windows\system32\rdpclip.exe 
    20/11/2010 11:22 

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Userinit 
    C:\Windows\system32\userinit.exe 

Jak to wygląda po wydrukowaniu w Pythonie:

Sysinternals Autoruns v13.51 - Autostart program viewer 
Copyright (C) 2002-2015 Mark Russinovich 
Sysinternals - www.sysinternals.com 


H K L M \ S y s t e m \ C u r r e n t C o n t r o l S e t \ C o n t r o l \ 
r m i n a l S e r v e r \ W d s \ r d p w d \ S t a r t u p P r o g r a m 
     r d p c l i p 
      r d p c l i p 
      R D P C l i p M o n i t o r 
      M i c r o s o f t C o r p o r a t i o n 
      6 . 1 . 7 6 0 1 . 1 7 5 1 4 
      c : \ w i n d o w s \ s y s t e m 3 2 \ r d p c l i p . e x e 
      2 0/1 1/2 0 1 0 1 1 : 2 2 

H K L M \ S O F T W A R E \ M i c r o s o f t \ W i n d o w s N T \ C u r 
n t V e r s i o n \ W i n l o g o n \ U s e r i n i t 

Możemy wyraźnie zobaczyć spacje i co ciekawe, w pierwszych kilku liniach nie uwzględniono spacji.

Jest to kod:

p = subprocess.Popen('autorunsc.exe /accepteula', stderr=subprocess.STDOUT, 
stdout=subprocess.PIPE, shell=True) 
a=p.stdout.read() 
print(a) 

Skąd przestrzenie pochodzę i jak mogę je usunąć?

+3

Najbardziej oczywistą odpowiedzią jest to, że jest wynikiem narzędzi Microsoftu wykorzystujących wewnętrznie UTF-16 zamiast UTF-8. –

+0

Czy rzeczywiście są to przestrzenie ASCII 0x20, w przeciwieństwie do NUL-ów? Zaryzykowałbym to drugie. –

+0

Co się dzieje, gdy zignorujesz 'stderr' (nie kieruję go do' STDOUT')? –

Odpowiedz

5

Format wyjściowy narzędzi Windows jest zakodowany w UTF-16.

Należy dekodować dane wyjściowe w celu poprawnego kodowania za pomocą metody str.decode. Cytowanie docs:

str.decode([encoding[, errors]])

dekoduje ciąg przy użyciu kodeka zarejestrowany dla kodowania. kodowanie domyślnie przyjmuje domyślne kodowanie ciągów znaków. można podać błędy, aby ustawić inny schemat obsługi błędów. Wartością domyślną jest "strict", co oznacza, że ​​błędy kodowania powodują wzrost UnicodeError. Inne możliwe wartości to "ignore", "replace" i dowolna inna nazwa zarejestrowana za pomocą kodeku codecs.register_error(), patrz rozdział Base Base Classes.

a=p.stdout.read().decode('UTF16') 

Na stole standardowych kodowań można wzorować się 7.8.3. Standard Encodings.

Ponieważ wyjście wydaje się mieć mieszane kodowanie [jak istnieje „przestrzeni” (które są naprawdę 0x00 znaków, a nie 0x20) tylko w części Output], może chcesz Preprocesuj lub podzielić swój ciąg przed wykonaniem dekodowania.

+0

To działa! Na wyjściu były znaki \ 0x00. kod .defode ("UTF16") zrobił lewę. Nie potrzebuję pierwszej porcji wyjścia i zawsze jest to stała długość, więc po prostu wydrukuję potrzebny kawałek. Dzięki – user3138929