PyQT5 textbrowser.append | command output encoding/decoding

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
BlackLeakz
User
Beiträge: 3
Registriert: Freitag 22. Juli 2022, 08:46

Hallo liebe Community,

ich würde gerne in Python3 , pyqt5 im Textbrowser das output des commands ('netsh wlan show networks') ausgeben . Leider ist das nicht so einfach wie gedacht und bisherige Recherche hat sich nicht gut verkauft...
Vielen Dank im vorraus.

Die simple cli-version ist diese:
(Problematik mit ! "" makiert.)

Code: Alles auswählen

#import subprocess
import os
import sys
import time
from time import sleep


def scan():
    print("Scanning..")
    #os.system('netsh wlan disconnect')
    disconnect()
    time.sleep(1.5)
    os.system('netsh wlan show networks')



def disconnect():
    print("Disconnecting.")
    os.system('netsh wlan disconnect')


def connect():
    print("Connecting.")


def tracing():
    print("Show tracing.")
    os.system('netsh wlan show tracing')


def interfaces():
    print("Show interfaces.")
    os.system('netsh wlan show interfaces')

def wlanreport():
    print("Wlanreport.")
    os.system('netsh wlan show wlanreport')

def all():
    print("Show all.")
    os.system('netsh wlan show all')

def main():
    while True:
        print("===============================")
        print("== WifiManager - v0.1        ==")
        print("===============================")
        print("=| 1: scan      | 2: connect |=")
        print("=| 3: interfaces| 4: tracing |=")
        print("=| 5: wlanreport| 6: all     |=")
        print("===============================")

        x = input("admin@WifiManager:~$ ")

        if x == "1":
            scan()
        if x == "2":
            connect()
        if x == "3":
            interfaces()
        if x == "4":
            tracing()
        if x == "5":
            wlanreport()
        if x == "6":
            all()



if __name__ == '__main__':
    main()

Diese würde ich gerne Übersetzen / in diesen Code umwandeln:

Code: Alles auswählen

# main.py
import sys
from PyQt5 import QtWidgets
from MainWindow import Ui_MainWindow

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi(self)


app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()


# Ui_file
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '/mnt/x/Development/Projekte/WIFIMGR_/mainwindow/form.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
import subprocess
import os
from subprocess import *

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.scanbtn = QtWidgets.QPushButton(self.centralwidget)
        self.scanbtn.setGeometry(QtCore.QRect(500, 410, 80, 24))
        self.scanbtn.setObjectName("scanbtn")
        self.scanbtn.clicked.connect(self.scanner)

        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect(70, 90, 641, 231))
        self.textBrowser.setObjectName("textBrowser")

        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "WifiManager"))
        self.scanbtn.setText(_translate("MainWindow", "scan"))

    def scanner(self):
        self.textBrowser.append("Start scanning.., disconnecting device to perform a full scan.")


!""
        #stdout = Popen('netsh wlan show networks', shell=True, stdout=PIPE).stdout
        output = stdout.read()

        #print(output)

!""
        #out = os.system('netsh wlan show networks')
        #new_ = out.encode(encoding='utf-8')
!""
        #self.textBrowser.append(subprocess.check_output('cmd /k netsh wlan show networks'))

Zuletzt geändert von BlackLeakz am Sonntag 2. Oktober 2022, 09:19, insgesamt 3-mal geändert.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Dann zeig doch mal, was du bisher hast.

Grundsätzlich startet man externe Prozesse mit dem "subprocess"-Modul. Die Dokumentation beschreibt auch, wie man an stdout kommt.
BlackLeakz
User
Beiträge: 3
Registriert: Freitag 22. Juli 2022, 08:46

sparrow hat geschrieben: Sonntag 2. Oktober 2022, 08:57 Dann zeig doch mal, was du bisher hast.

Grundsätzlich startet man externe Prozesse mit dem "subprocess"-Modul. Die Dokumentation beschreibt auch, wie man an stdout kommt.
added <3
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Bevor man anfängt, irgendwas mit externen Programmen abzufragen, schaut man, ob man an die Information auch direkt kommt. Und dafür hat Windows allerhand Schnittstellen, zu denen es auch oft schon Python-Wrapper gibt, wie hier https://pypi.org/project/win32wifi/.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@BlackLeakz: Erst einmal ist das erste nicht wirklich Python. Wenn man im Grunde nur `print()`, `input()`, Schleifen hat, und ansonsten nur externe Programme aufruft, dann ist das eigentlich ein Shell-Skript das sich als Python-Programm verkleidet hat. Passt irgendwie in die Jahreszeit — Halloween — muss aber nicht wirklich sein. Ungetestet:

Code: Alles auswählen

#!/bin/bash
 
Main() {
    local input
    
    while true; do
        echo '==============================='
        echo '== WifiManager - v0.1        =='
        echo '==============================='
        echo '=| 1: scan      | 2: connect |='
        echo '=| 3: interfaces| 4: tracing |='
        echo '=| 5: wlanreport| 6: all     |='
        echo '==============================='
        read -r -p 'admin@WifiManager:~$ ' input
        case $input in
            1)
                echo 'Scanning...'
                echo 'Disconnecting...'
                netsh wlan disconnect
                sleep 1.5
                netsh wlan show networks
                ;;
            2)
                echo 'Connecting...'
                ;;
            3)
                echo 'Show interfaces.'
                netsh wlan show interfaces
                ;;
            4)
                echo 'Show tracing.'
                netsh wlan show tracing
                ;;
            5)
                echo 'Wlanreport.'
                netsh wlan show wlanreport
                ;;
            6)
                echo 'Show all.'
                netsh wlan show all
                ;;
        esac
    done
}

[[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"
Dann steht in der aus der *.ui-Datei generierten Quelltextdatei ganz deutlich eine Warnung das man da nichts ändern oder hinzufügen soll, weil man dann ja nichts mehr an der *.ui-Datei ändern kann wenn beim erneuten generieren die ganzen manuellen Änderungen verloren gehen.

Man generiert heutzutage diese Quelltextdatei nicht mehr, sondern lädt die *.ui-Datei zur Laufzeit mit Hilfe des `PyQt5.uic`-Moduls.

Sternchen-Importe sind Böse™. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen sollten keine kryptischen Abkürzungen enthalten. Wenn man `scanButton` meint, sollte man nicht `scanbtn` schreiben.

Im generierten Quelltext sieht man, dass sowohl Fenstergrösse als auch Grösse und Positionen der Widgets in dem Fenster fest vorgegeben sind statt Layouts zu verwenden. Feste Pixelangaben funktionieren nicht wirklich. Entweder hat man viel zu viel Platz um die Elemente, oder es kann bei anderen Bildschirmgrössen, -auflösungen, und Systemeinstellungen sogar unbenutzbar werden, wenn Elemente sich überlappen oder nicht mehr im sichtbaren Bereich des Fenster liegen.

``shell=True`` sollte man bei `subprocess` meiden, denn damit fängt man sich die gleichen Programe ein weswegen man `os.system()` nicht verwenden sollte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten