Strona główna Polish Python Coders Group
   Strona główna   Pomoc Zaloguj się Rejestracja  
Witamy, Gość. Zaloguj się lub zarejestruj.
Czy dotarł do Ciebie email aktywacyjny?

Zaloguj się podając nazwę użytkownika, hasło i długość sesji

Aktualności: PyStok #24 - 25 kwietnia, 18:00, Białystok!
Szukaj Szukaj
Strony: [1]   Do dołu
Drukuj
Wątek: Problem z wierszem poleceń w Windowsach innych niż 10  (Przeczytany 250 razy)
« : 13:23 18/04/17 »
Grzesiek Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 7


W przypadku kiedy chcę z poziomu Pythona odczytać wynik windowsowego polecenia w trybie tekstowym w Win10 nie ma z tym problemu w Win7 i Vista otrzymuję błąd.
W przypadku prostego polecenia 'dir' nie ma problemu i wszystkie Windowsy radzą sobie tak samo.
Jak to ugryźć?
Przykładowy kod generujący błąd:
Kod
import os
 
cmd = 'netsh wlan show profiles'
fin = os.popen(cmd)
for line in fin.readlines():
print(line)
 
Komunikat błędu:
Kod
Traceback (most recent call last):
 File "cmdtest.py", line 5, in <module>
   print(fin.read())
 File "C:\Users\user\AppData\Local\Programs\Python\Python36-32\lib\encodings\cp1250.py", line 23, in decode
   return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x88 in position 26: character maps to <undefined>
 
Zapisane
« Odpowiedz #1 : 13:39 18/04/17 »
pycoder_pl Offline
Hello World!

Zobacz profil
*

Reputacja: 6
Płeć: Mężczyzna
Wiadomości: 89


Nie mam niestety żadnej "windy" po ręką, ale zerknij może z kodowaniem:

Kod
print(line).encode('UTF-8')
Zapisane

--
pozdrawiam
Paweł
« Odpowiedz #2 : 09:59 19/04/17 »
Grzesiek Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 7


Dzięki, ale niestety ten sposób nie działa :-(
Zapisane
« Odpowiedz #3 : 19:29 19/04/17 »
guest013 Offline
Hello World!

Zobacz profil
*

Reputacja: 3
Płeć: Mężczyzna
Wiadomości: 52


Jak dla mnie to trochę namieszałeś w kodzie bo poniższy kod działa na Win7

Kod
import os
 
os.system('netsh wlan show profiles')

skrypt odpalony z poziomu cmd działa i wyświetla to co powinien.

Metoda readlines() ma zastosowanie przy plikach tekstowych do odczytu kolejnych linijek tekstu, a u ciebie nie ma mowy o jakimkolwiek pliku
Zapisane
« Odpowiedz #4 : 22:34 19/04/17 »
Grzesiek Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 7


Masz rację, ale metoda readlines() lub read() jest mi potrzebna aby przetworzyć wyniki polecenia czyli konkretnie chodzi mi o zapisanie listy sieci bezprzewodowych np. na liście lub w słowniku w celu późniejszego wykorzystania.  Kiedy użyję tych metod to wtedy pojawia się problem.
Zapisane
« Odpowiedz #5 : 23:01 19/04/17 »
guest013 Offline
Hello World!

Zobacz profil
*

Reputacja: 3
Płeć: Mężczyzna
Wiadomości: 52


Sprawa jest prosta. Ja swój powyższy skrypt nazwałem test.py a wynik będę zapisywał do pliku test.txt .W cmd należy wpisać:

Kod
python test.py > test.txt

to spowoduje zapisanie wyniku skryptu do pliku, z którego już możesz czytać.

Kod
with open('test.txt', 'r', encoding='iso-8859-2') as file:
   data = file.readlines()
   for line in data:
       print(line)

Dodałem kodowanie, które win7 potrzebuje.

Edit
Jeśli chciałbyś się się dostać do konkretnej linijki wystarczy zrobić tak:

Kod
with open('test.txt', 'r', encoding='iso-8859-2') as file:
   data = file.readlines()
   print(data[-2])

data[-2] bo ostatnia linijka jest pusta (w przypadku, gdy jest jedna nazwa - dla większej ilości użyj innego 'cięcia' Mrugnięcie ). Możesz się pobawić z metodami replace() i strip() dla dokładniejszego wyniku Mrugnięcie Zapisz do zmiennej i już masz nazwę której szukasz do dalszego wykorzystania.
Zapisane
« Odpowiedz #6 : 20:08 20/04/17 »
Grzesiek Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 7


Niestety w moim win7 wpisanie:
Kod
python skrypt.py > plik.txt
daje identyczny błąd jak opisywałem wcześniej w win10 jest bez problemu. Trudno, to jest pewnie jakiś problem z kodowaniem który występuje w niektórych wersjach windows.
Metoda os.popen() jest już podobno właściwie wycofywana z użycia, ale kiedy zastąpię ją
Kod
cmd = 'polecenie' 
subprocess.Popen(cmd)
to nie wiem jak mogę wydobyć jakieś dane z tego obiektu bo tu read() nie działa. Pytanie jest takie jak można inaczej niż przez read()/readline()/readlines() dostać się do obiektu, który powstaje po wykonaniu polecenia subprocess.Popen(cmd).
Zapisane
« Odpowiedz #7 : 20:59 20/04/17 »
guest013 Offline
Hello World!

Zobacz profil
*

Reputacja: 3
Płeć: Mężczyzna
Wiadomości: 52


Skoro nie moja podpowiedź, to rada jak zwykle -> dokumentacja:

https://docs.python.org/3.4/library/subprocess.html

Być może pycoder_pl ma rację co do kodowania, bo tego właśnie dotyczy twój error. I jeśli UTF-8 nie działa to spróbuj ISO-8859-2 albo innych (te 2 są najczęściej wykorzystywane)
Zapisane
« Odpowiedz #8 : 21:14 20/04/17 »
sztosz Offline
Expert Python User

Zobacz profil WWW
****

Reputacja: 74
Płeć: Mężczyzna
Wiadomości: 579


W starych polskich windowsach to raczej cp1250 a nie ISO jest wykorzystywane.
Zapisane
« Odpowiedz #9 : 10:26 21/04/17 »
Guaz Offline
Hello World!

Zobacz profil
*

Reputacja: 4
Płeć: Mężczyzna
Wiadomości: 46


Wynik powinieneś móc przekierować z poziomu programu przez konsolę do pliku. Przynajmniej tak mi się wydaje, ale windowsa nie używam (może raz w miesiącu włączę na godzinę by mnie update'y nie zabiły gdybym potrzebował do programów graficznych się dostać ;p).
Kod:
os.system("your_command > " + nazwa_pliku*)
*jeśli to ma być zmienna wielokrotnego użytku, w innym wypadku po prostu w stringu po > zawrzyj
Plik powinien ci się utworzyć w katalogu, w którym odpaliłeś program pythonowy.

Później jak nadmieniono wyżej spróbuj try'ami*, aż zadziała jakieś kodowanie. Polecam też spróbować otworzyć binarnie (tylko po to aby zweryfikować czy się da otworzyć). Sprawdź też czy masz prawa do czytania/zapisywania tych plików, jeśli nie, to nadaj je przez pakiet os. (jestem laikiem, może gadam głupoty, ale może w tym konkretnym przypadku python źle zczytuje błąd i nie leży w kodowaniu. <shrugs> Ja nigdy nie ufam maszynie dopóki nie działa jak powinno ;P)

*try by zrobić od razu kilka testów, zobaczyć gdzie się rozkrzacza, a gdzie coś załapie ;p.
np:
Kod
try:
   file=open('test.txt', 'r', encoding='iso-8859-2')
except:
   print("Błąd w iso-8859-2")
   try:
       file=open('test.txt', 'rb')
   except:
       print("Błąd w odczycie binarnym")
       try:
           file=open('test.txt', 'r', encoding='cp1250')
... itd.
 
Zapisane

Python 3.5.2 / Mint
« Odpowiedz #10 : 16:04 22/04/17 »
Grzesiek Offline
Hello World!

Zobacz profil
*

Reputacja: 0
Płeć: Mężczyzna
Wiadomości: 7


Eureka ;-)
Znalazłem rozwiązanie, otóż jest to rzeczywiście problem z kodowaniem znaków w konsoli Windowsa. Zamiast funkcji os.popen() użyłem subprocess.Popen(). Ta funkcja jest trudniejsza w zastosowaniu, ale zwraca wynik polecenia w postaci łańcucha bajtowego. Dzięki temu nie ma problemów z kodowaniem. Otrzymany łańcuch możemy zdekodować za pomocą metody decode('cp852') w której jako argument podajemy rodzaj kodowania. W przypadku moich Windowsów (Vista i 7) okazało się że chodzi o cp852. Po zdekodowaniu mamy zapisany w zmiennej gotowy do dalszej obróbki łańcuch typu str. Kodowanie odnalazłem w ten sposób że w otrzymanym łańcuchu bajtowym litera ł byłą reprezentowana przez liczbę \x88 sprawdziłem w Wikipedii https://pl.wikipedia.org/wiki/Kodowanie_polskich_znak%C3%B3w że w ten sposób koduje standard cp852.
Kod
import subprocess
 
coding = 'cp852'
command = subprocess.Popen('netsh wlan show profiles', stdout=subprocess.PIPE)
outcome = command.stdout.read().decode(coding)
print(outcome)
Zobaczcie czy u Was też to tak działa. W każdym razie dzięki za wszystkie podpowiedzi i inspiracje.
Zapisane
Strony: [1]   Do góry
Drukuj
Skocz do:  

© 2007 - 2017 Polish Python Coders Group
Powered by SMF 1.1.21 | SMF © 2006-2009, Simple Machines | Theme by PixelSlot