[LINUX] [Verbesserte Version] Skript zur Überwachung der CPU mit Python

Wenn ich temp.py in Messen Sie die CPU-Temperatur von Raspeye mit Python ausführe, das ich zuvor geschrieben habe, wird die Anzahl der CPUs jedes Mal gezählt, wenn es in einer while-Schleife ausgelöst wird. Ich habe einen Prozentsatz verwendet. Da es sich um ein Überwachungsskript handelt, möchte ich es verbessern, da es so leicht wie möglich sein sollte.

Übrigens sieht die Ausgabe nach der Verbesserung so aus. Von links CPU-Temperatur, Häufigkeit, Gesamtnutzungsrate und Nutzungsrate für jeden Kern. 110255.png

Ursache

Was schwer war, war das Modul namens "Subprozess", das zum Ausführen von Linux-Betriebssystembefehlen verwendet wurde. Diesbezüglich Es ist falsch, mit Pythons Unterprozess zu katzen. , also schauen Sie bitte. Einfach ausgedrückt ist es langsam, da ein untergeordneter Prozess gestartet wird, um den Text abzurufen. Wenn Sie die integrierte Funktion für den Dateivorgang namens "open ()" verwenden, wird sie nur in Python ausgeführt, sodass sie etwa 50-mal schneller ist.

Verbesserungspunkte

Es gibt vier Hauptverbesserungen.

  1. Ersetzen Sie subprocess durch open ()
  2. Die Schleife von "while" ist langsam, ersetzen Sie sie also durch "for"
  3. Schreiben Sie die Zeichenfolgenoperation in print mit Format neu
  4. Die Betriebsspannungsanzeige wurde abgeschafft und die Nutzungsrate angezeigt

Der erste ist der Höhepunkt dieser Zeit. Zuvor habe ich "subprocess" verwendet, um einen von Raspberry Pi OS erstellten Befehl namens "vcgencmd" auszuführen. Dies kann nur unter Raspberry Pi OS ausgeführt werden, und vcgencmd wurde für die Ausführung in der Shell entwickelt, sodass es nicht für das Schlagen von Python geeignet ist. Die Überwachung in Python ist eine Unterprozessbombe, die nur ein Name ist. Daher ist sie eine Unterfunktion dieser Zeit, um CPU-Informationen ohne Verwendung von "vcgencmd" abzurufen.

Der zweite ist unbedeutend, aber ich habe ihn in einer Stimmung umgeschrieben. Der dritte dient hauptsächlich der Verbesserung der Lesbarkeit. Viertens fand ich nicht viel Verdienst bei der Überprüfung der Betriebsspannung, und ich konnte die Datei, die die Betriebsspannung aufzeichnete, nicht finden. Geändert, um stattdessen die CPU-Auslastung anzuzeigen.

Code

Hier ist der verbesserte Code.

temp.py


#!/usr/bin/python3.7

import time
import sys

#Funktion zur Erfassung der CPU-Nutzungszeit
def get_data():
    with open('/proc/stat') as r: #CPU-Statistikdatei lesen
        stats = r.readlines() #Liste nach Zeile
        stat = [line.strip().split() for line in stats if 'cpu' in line] #Nehmen Sie die Zeile mit der CPU auf und entfernen Sie das Zeilenvorschubzeichen, doppelte Liste durch Leerzeichen getrennt
    rs = [] #Deklarieren Sie eine Liste, die die Nutzungszeit enthält
    for data in stat: #Extrahieren Sie Daten für die gesamte CPU und jeden logischen Kern aus Statistiken
        busy = int(data[1]) + int(data[2]) + int(data[3]) #Finden Sie die Zeit des Besetztzustands
        all = busy + int(data[4]) #Fragen Sie die ganze Zeit
        rs.append([all, busy]) #Zur Liste hinzufügen
    return rs #Gibt einen Wert zurück

pre_data = get_data() #Holen Sie sich die erste CPU-Auslastungszeit
ave = 0 #Variablendeklaration zur Durchschnittsberechnung

time.sleep(1) #Warten Sie eine Sekunde

try: #Strg mit der folgenden Taste außer Keyboard Interrupt+Normalbetriebsteil zum Fangen C.
    for i in range(60): #60 mal wiederholen
        with open('/sys/class/thermal/thermal_zone0/temp') as t: #CPU-Temperaturmessung
            temp = int(t.read()) / 1000 #Typkonvertierungs- und Übereinstimmungseinheiten
        with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq') as f: #CPU-Frequenzmessung
            freq = int(f.read()) #Typkonvertierung

        now_data = get_data() #Aktuelle CPU-Auslastungszeit abrufen
        rates = [] #Deklarieren Sie eine Liste mit der CPU-Auslastung

        for j in range(5): #Ganze CPU+Anzahl der logischen Kerne(4)Wiederholen Sie die Zeiten
            now = now_data[j] #Extrahieren Sie die gewünschten CPU-Daten aus der aktuellen Nutzungsdauer
            pre = pre_data[j] #Extrahieren Sie die gewünschten CPU-Daten aus der Nutzungszeit vor 1 Sekunde
            rate = (now[1] - pre[1]) / (now[0] - pre[0]) * 100 #(Besetztzustand/Das ganze) *Finden Sie die CPU-Auslastung bei 100
            rates.append(rate) #Fügen Sie der Liste die CPU-Auslastung hinzu

        #Formatieren und exportieren Sie mit der Formatierungsmethode
        print("Temp:{0:>6.2f}'C, Freq: {1:.2f}GHz, CPU:{2:>5.1f}% [{3:>3.0f},{4:>3.0f},{5:>3.0f},{6:>3.0f}]({7:>2})".format(temp, freq / 1000000, rates[0], rates[1], rates[2], rates[3], rates[4], i + 1))

        ave += temp #Addieren Sie die aktuelle Temperatur für die Durchschnittstemperatur
        pre_data = now_data #Speichern Sie die aktuellen Daten für die nächsten zweiten vorherigen Daten
        time.sleep(1) #Warten Sie eine Sekunde
    print("Average: {:.2f}'C (60s)".format(ave / 60)) #Schreiben Sie den Durchschnitt nach dem Ende der Schleife
except KeyboardInterrupt: #Ctrl+Fang C.
    sec = i + 1 #Holen Sie sich die verstrichene Zeit am Ende
    print(" Aborted.\nAverage: {0:.2f}'C ({1}s)".format(ave / sec, sec)) #Schreiben Sie die Durchschnittstemperatur auf
    sys.exit() #Erfolgreiche Fertigstellung

CPU auslastung

Vor der Erläuterung möchte ich beschreiben, wie die CPU-Auslastungsrate separat berechnet wird. Ich habe auf [hier] verwiesen (http://my-web-site.iobb.net/~yuki/2017-10/raspberry-pi/cpustat/).

Die CPU-Auslastungsrate ist im Grunde das Verhältnis der Zeit, in der die CPU ausgelastet war, zur Gesamtzeit. Wenn Sie also die CPU-Auslastungszeit aus den von Ubuntu bereitgestellten CPU-Statistiken erhalten, können Sie sie nach dem folgenden Prinzip abrufen.

Kumulative CPU-Verfügbarkeit(s) ... 904 905 906 907 908 ...
Kumulative Besetztzeit(s) ... 302 302.5 302.6 303 303 ...
Differenzielle CPU-Betriebszeit(s) ... 1 1 1 1 1 ...
Differenz Besetztzeit(s) ... - 0.5 0.1 0.4 0 ...
CPU auslastung(%) ... - 50% 10% 40% 0% ...

Der allgemeine Codefluss lautet "Datenerfassung (vor)" -> "1 Sekunde warten" -> "Datenerfassung (jetzt und nächste vor)" -> "Berechnung" -> "Datenerfassung (jetzt als nächstes)" -> (Wiederholen) ..

Die Ubuntu-CPU-Statistiken sind in / proc / stat aufgeführt. Das Folgende ist ein Auszug aus dem Handbuch.

man


/proc/stat
    kernel/system statistics.  Varies with architecture.  Common entries include:
        cpu 10132153 290696 3084719 46828483 16683 0 25195 0 175628 0
        cpu0 1393280 32966 572056 13343292 6130 0 17875 0 23933 0
        #Formatieren Sie die obige Zeichenfolge so, dass sie wie rechts aussieht[[cpu, 10132153, 290696, 3084719, 46828483, 16683, 0, 25195, 0, 175628, 0], [cpu0, 1393280, 32966, 572056, 13343292, 6130, 0, 17875, 0, 23933, 0]]
            The amount of time, measured in units of USER_HZ (1/100ths of a second on most architectures, use sysconf(_SC_CLK_TCK) to obtain the right value), that the system ("cpu" line) or the specific CPU ("cpuN" line) spent in various states:
                user   (1) Time spent in user mode. #Vom Benutzer beschäftigt
                nice   (2) Time spent in user mode with low priority (nice). #Beschäftigt aufgrund von Prozessen mit niedriger Priorität durch Benutzer
                system (3) Time spent in system mode. #Vom System besetzt
                idle   (4) Time spent in the idle task.  This value should be USER_HZ times the second entry in the /proc/uptime pseudo-file. #Idol

Wir werden es so formatieren, dass Sie die erforderlichen Daten abrufen können, indem Sie darauf verweisen. Wenn Sie es mit "subprocess" erhalten, gibt es einen praktischen namens "grep", aber Sie können es diesmal nicht verwenden. Verwenden Sie also die in open () enthaltenen Readlines (). Lesen Sie den Artikel hier, reproduzieren Sie das gleiche Verhalten wie "grep" und verarbeiten Sie es weiter, um "CPU> item" zu verdoppeln. Machen Sie eine Liste. (Siehe Kommentare im obigen Handbuch)

Aus dieser Doppelliste nimmt "for" die Daten für die gesamte CPU und jeden logischen Kern heraus, berechnet den Besetztzustand und die gesamte verstrichene Zeit und gibt sie als Doppelliste der "verstrichenen CPU und des logischen Kerns> verstrichene Zeit" zurück. Hier ist die Summe der 2., 3. und 4. Elemente in der Liste die Summe des Besetztzustands, und die Summe des Besetztzustands und des Leerlaufzustands (das 5. Element) ist die insgesamt verstrichene Zeit. Das Obige ist die Verarbeitung der Nutzungszeiterfassungsfunktion "get_data ()". Danach möchte ich in der Erklärung darauf eingehen.

Kommentar

Ich habe es in den Kommentaren geschrieben, aber ich würde es gerne in der Reihenfolge von oben behandeln. Ich bin selbst ein Anfänger, also werde ich es im Übermaß erklären.

import Importieren Sie zunächst die erforderlichen Module. Diesmal habe ich das time Modul für den Standby und das sys Modul für die Terminierung geladen. Darüber hinaus enthielt der vorverbesserte Code "Unterprozess", aber ich habe ihn entfernt.

def get_data() Wir haben uns bereits in einem anderen Abschnitt mit der CPU-Auslastung befasst, aber wir haben eine Funktion deklariert, um die kumulative Nutzungszeit mit def zu erhalten.

pre_data und ave,time.sleep (1)

Holen Sie sich vor dem Eintritt in die Schleife die Daten für die Erstberechnung und deklarieren Sie eine Variable zur Berechnung der durchschnittlichen CPU-Temperatur. Warten Sie dann eine Sekunde. Wenn Sie fortfahren, ohne zu warten, wird now_data früher als das Aktualisierungsintervall von / proc / stat erfasst, sodass die Differenz Null ist und Sie wütend werden, wenn Sie nicht durch 0 teilen.

"versuchen" und "außer"

Durch Einschließen der gesamten Schleife in "try" kann die Eingabe von "Strg + C" als Ausnahme anstelle eines Fehlers abgefangen werden. Wenn "Strg + C" eingegeben wird, springt es zu "außer Tastaturunterbrechung", berechnet die Durchschnittstemperatur und endet dann normal.

for i in range(60) Es wiederholt den Vorgang, während i durch Zahlen von 0 bis 59 ersetzt wird. Es scheint, dass 10000000-maliges Wiederholen schneller ist als das Wiederholen mit "while" für etwa 0,04 Sekunden. Diesmal liegt es nicht im Fehlerbereich, aber ich mag die Tatsache, dass ich keinen Zähler vorbereiten muss, weil er intelligent ist.

with open() Eine integrierte Funktion, die die Datei öffnet, die im Auftrag von "subprocess" eingeführt wurde. Wie oben erwähnt, finden Sie Einzelheiten hier hier. Da die Verarbeitung in Python abgeschlossen ist, trägt sie zur Gewichtsreduzierung bei.

now_data und Rates

Sie erhalten die aktuelle kumulative CPU-Auslastungszeit. Deklariert eine leere Liste zum Ersetzen der CPU-Auslastung.

for j in range(5) Daten werden für die gesamte CPU und jeden Kern abgerufen und verarbeitet. Berechnet die CPU-Auslastung, indem die Differenz zwischen der aktuellen kumulierten Nutzungszeit now_data und der kumulierten Nutzungszeit pre_data vor einer Sekunde berechnet wird, und gibt das Ergebnis als Liste zurück. (Wie soll ich einen Index nennen, der nicht "i" ist?)

print Es ist so geschrieben, dass es mit der Formatmethode leicht zu erkennen ist. Dies ist sehr praktisch, da Sie einfache Berechnungen durchführen können, z. B. den Durchschnittswert innerhalb des Formats teilen.

ave und pre_data,time.sleep (1)

Die aktuelle Temperatur wird zu "ave" addiert, um die durchschnittliche Temperatur zu erhalten. Ersetzen Sie "pre_data" durch die zuvor erhaltenen aktuellen Daten für die nächste Berechnung der CPU-Auslastung. Nach einer Sekunde Wartezeit wird der Prozess wiederholt.

Erhalten Sie CPU-Informationen, ohne vcgencmd zu verwenden

Wie bereits erwähnt, ist das Abrufen von Informationen aus Python mit vcgencmd sehr ineffizient. Da die Daten von Ubuntu wie / proc / stat in eine Datei umgewandelt werden, habe ich versucht, sie von dort abzurufen.

CPU-Temperatur

Ich denke, das ist ein ziemlich berühmter Ort.

cat /sys/class/thermal/thermal_zone0/temp
#1000-fache Temperatur wird ausgegeben

Mit vcgencmd werden Einheiten usw. angehängt, aber da es sich nur um eine Zahl handelt, scheint es besser, sie von hier aus in das Skript einzubetten. Teilen ist kein Problem, wenn es im Programm enthalten ist, und aus irgendeinem Grund ist es gut, dass die gültigen Zahlen größer sind.

CPU-Frequenz

Es fiel mir schwer, das zu finden, aber auf jeden Fall gibt es großartige Männer. Vielen Dank.

Ubuntu CPUfreq Teil 3 - Informationen zu den Dateien im Ordner cpufreq der CPU

#/sys/devices/system/cpu/cpu*/CPU-Frequenz zu CPU(Ader)Informationen werden gesammelt
#cpuinfo_cur_freq ist der von der Hardware erhaltene Wert
#scaling_cur_freq ist der vom Linux-Kernel erhaltene Wert

cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq
#Permission denied
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
#Die CPU-Frequenz von cpu0 wird angezeigt

Es ist schön, einen Platz zu finden, aber ich hatte zwei Probleme. Das erste ist, dass Sie "root" nur für die von der Hardware erhaltenen Zahlen sehen können, und das andere ist, dass die Dateien für jeden CPU-Kern unterschiedlich sind. Wenn möglich, möchte ich auf den von der Hardware erhaltenen numerischen Wert verweisen, möchte ihn jedoch ohne "root" ausführen. Wenn die Frequenz für jeden CPU-Kern unterschiedlich ist, möchte ich den Durchschnitt nehmen, aber ich möchte ihn vermeiden, da sich die Verarbeitung vervierfacht.

Um diese Probleme zu lösen, habe ich versucht, sie mit brutaler Gewalt zu überprüfen. Wenn alle acht Werte übereinstimmen, gibt es meines Erachtens auch dann kein Problem, wenn ein Wert als repräsentatives Beispiel verwendet wird. Erfassen und vergleichen Sie also 10000 Mal "cpuinfo_cur_freq" und "scaling_cur_freq" aller 4 Kerne. Infolgedessen stimmten alle mit einer Rate von etwa 95% überein. Es scheint, dass es eine Verschiebung beim Ändern der Frequenz gibt, und wenn Sie zwischen den Überprüfungen einen Schlaf einlegen, waren es ungefähr 95%, und wenn Sie nichts getan und wiederholt haben, war es 100% konsistent. Es scheint auch, dass die Abweichung hauptsächlich zwischen der Hardware und dem Kernel auftritt und die Übereinstimmung zwischen den Kernen im schlimmsten Fall etwa 99% betrug. Es muss nicht so streng sein, und das Abtasten jeder Sekunde hat nur geringe Auswirkungen. Deshalb habe ich mich dieses Mal entschieden, scaling_cur_freq von cpu0 als repräsentativen Wert zu verwenden.

Unter Linux (in Raspberry Pi?) Steuern Sie nicht, wie Sie Strom sparen, indem Sie die Frequenz für jeden Kern ändern. Ich würde mich freuen, wenn Sie mich wissen lassen könnten, ob jemand mit diesem Bereich vertraut ist.

CPU-Spannung

Wir konnten den Speicherort der Datei nicht finden. Sie können es finden, wenn Sie ernsthaft danach suchen, aber da es ein Wert war, der ursprünglich nicht sein musste, habe ich beschlossen, ihn zu diesem Zeitpunkt zu schneiden. Wenn jemand weiß, lassen Sie es mich bitte wissen.

Zusammenfassung

Ich fing an, das Gewicht schwerer Skripte zu reduzieren, und da ich die CPU mit Python überwachte, fügte ich den Zweck hinzu, sie nur mit Python zu vervollständigen, und am Ende gelang es mir, das Gewicht signifikant zu reduzieren. Ich bin mir meiner täglichen Studien sehr bewusst, weil ich etwas über super nützliche Funktionen lernen kann, die ich nicht kannte. Ich konnte es auch ein wenig verfeinern, indem ich den Code beim Schreiben dieses Artikels neu schrieb. Überprüfung ist wichtig. Es war ein langer Artikel, aber danke, dass Sie bis zum Ende gelesen haben. Wenn Sie Vorschläge haben, können Sie sich gerne an uns wenden.

Recommended Posts

[Verbesserte Version] Skript zur Überwachung der CPU mit Python
Überprüfen Sie die Version mit Python
Python-Skript zum Abrufen von Notizinformationen mit REAPER
So fügen Sie HDA Hilfe hinzu (mit Python-Skriptbonus)
Stellen Sie mit Python eine Verbindung zu Wikipedia her
Post to Slack mit Python 3
Schalten Sie Python mit Alternativen auf 2.7 um
Schreiben Sie mit Python in csv
Einführung in Python (Python-Version APG4b)
So ändern Sie die Python-Version
Geben Sie die Python-Version mit virtualenv an
Ich möchte eine andere Version von Python mit pyvenv angeben
Python: So verwenden Sie Async mit
Link, um mit Python zu beginnen
[Python] Mit Python in eine CSV-Datei schreiben
Schön dich mit Python zu treffen
Versuchen Sie, Facebook mit Python zu betreiben
Ausgabe in eine CSV-Datei mit Python
Überwachen Sie Python-Webanwendungen mit Prometheus
Überwachen Sie die Leistung von Python-Anwendungen mit Dynatrace ♪
So erhalten Sie die Python-Version
Konvertieren Sie die Liste mit Python in DataFrame
MP3 → WAV-Konvertierung mit Python
[Python] Kopierskript zum Generieren eines Kopierprotokolls
Schwanzrekursion mit Python2 durchführen
Erste Schritte mit Python
Was tun mit PYTHON Release?
Verwalten Sie jede Python-Version mit Homebrew
So berechnen Sie das Datum mit Python
Mit Python 3 einfach auf Twitter posten
Ich möchte mit Python debuggen
Python-Version, um nicht verwendete Ports zu erhalten
Schreiben Sie ein Batch-Skript mit Python3.5 ~
[AWS SAM] Einführung in die Python-Version
So installieren Sie Chrome Driver für Chrome automatisch mit Python + Selenium + Chrome
Konvertieren Sie in PyTorch geschriebenes Python-Skript mit PyInstaller in exe
ImportError beim Versuch, das gcloud-Paket mit der AWS Lambda Python-Version zu verwenden
[Blender] So legen Sie shape_key mit dem Skript fest
Versuchen Sie, Farbfilme mit Python zu reproduzieren
Versuchen Sie, sich mit Python bei qiita anzumelden
Ändern Sie die Python 64-Bit-Umgebung mit Anaconda in eine 32-Bit-Umgebung
Englische Spracherkennung mit Python [Rede zu Text]
Konvertieren Sie Memos sofort mit Python 2to3
HTML-Mail mit Bild zum Senden mit Python
[Yahoo! Weather Replacement Version] So erhalten Sie Wetterinformationen mit LINE Notify + Python
Memo, um nach KPI mit Python zu fragen
Python nur mit Hallo, Welten zu erinnern
Führen Sie das Python-Skript mit TS-220 cron aus
Geben Sie Farbzeichen mit Python zu hübsch aus
Pin aktuelles Verzeichnis an Skriptverzeichnis in Python
Wenn Sie awsebcli in CircleCI aufnehmen möchten, geben Sie die Python-Version an
Beispielskript zum Überfüllen von Signalen in Python
Python-Protokoll mit GAE an die Konsole ausgeben
Konvertieren Sie Excel-Daten mit Python in JSON
Konvertiere Hiragana mit Python (Beta) in Romaji