Leistung von Skript verringern (while loop)

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
zar1
User
Beiträge: 39
Registriert: Samstag 28. Dezember 2013, 01:08

Hallo ich habe ein Programm entwtickelt,das erkennt ob eine Taste, die man davor ausgewählt hat, gedrückt ist und ob sie gedrückt bleibt. Wenn diese Taste losgeelassen wird klickt Python dann mti der Maus irgendwo hin.

Das Problem ist dieses Programm verbraucht relativ viel Arbeitsspeicher, da es die ganze Zeit eine While - Schleife am laufen hat um zu erkennen ob eine Taste gedrückt ist und wielange sie gedrückt bleibt.

Daher wollte ich fragen ob ihr eine Möglichkeit kennt wie ich die Leistung, die das Programm verbraucht, erheblich verringern kann, das Ergebnis aber das gleiche bleibt.

Hier der Code:

Code: Alles auswählen

import win32api
import win32con, time, tkinter
import win32api, win32gui, win32con, os ,time
def middle(x,y):
    win32api.SetCursorPos((x,y))
    win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEDOWN,x,y,0,0)
    time.sleep(.02)
    win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEUP,x,y,0,0)
    time.sleep(.02)
def click(x,y):
    win32api.SetCursorPos((x,y)) # 0.02 ist das Minimum
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
    time.sleep(.02)
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def get_coords():
    x,y = win32api.GetCursorPos()
    return x,y
def setc(x,y):
    coords = x,y

    win32api.SetCursorPos(coords)
    
    time.sleep(.02)

main = tkinter.Tk()
main.title("Zar1's skillshothelper")

lbl1 = tkinter.Label(main, text = "type in on which keys you have your four spells in UPPER CASE!!! (eg: Q )")
                     
lbl1.pack()
lb2 = tkinter.Label(main, text = "if you don't want that this program affect a key typ in a lower case letter.")
lb2.pack()
e = tkinter.Entry(main,width = 4,)
e.pack()
e1 = tkinter.Entry(main,width = 4)
e1.pack()
e2 = tkinter.Entry(main,width = 4)
e2.pack()
e3 = tkinter.Entry(main, width = 4)
e3.pack()


def userdata():
    c = 0
    d = 0
    i0 = e.get()
    i1 = e1.get()
    i2 = e2.get()
    i3 = e3.get()
    while(1):
        a = win32api.GetAsyncKeyState(ord(i0))
        a1 = win32api.GetAsyncKeyState(ord(i1))
        a2 = win32api.GetAsyncKeyState(ord(i2))
        a3 = win32api.GetAsyncKeyState(ord(i3))
        if a or a1 or a2 or a3 == 0:
            d = d+1
            if a or a1 or a2 or a3 != 0:
                d = 0
            if d == 1:
                 gc = get_coords()
                 gc0 = gc[0]
                 gc1 = gc[1]
                 click(gc0,gc1)
               

btest = tkinter.Button(main, text = "Start",
                       command = userdata, height=2, width= 8,
                       font = "Arial 11 bold")
btest.pack()

lb3 = tkinter.Label(main, text = "made by zar1")
lb3.pack()

lb4 = tkinter.Label(main, text = "youtube.com/zbrotherz")
lb4.pack()

        
        

main.mainloop()
BlackJack

@zar1: Verwende eine andere Programmiersprache. Assembler würde sich anbieten, denn damit bekommt man sicher Programmcode und Speicherverbrauch am kleinsten hin, und übersichtlich und lesbar scheint Dir ja sowieso nicht wichtig zu sein. :twisted:
zar1
User
Beiträge: 39
Registriert: Samstag 28. Dezember 2013, 01:08

Da das GUI vielleicht ein bisschen verwirrt / vom Thema ablenkt hier nochmal ohne Tkinter:

Code: Alles auswählen

import win32api
import win32con, time
import win32api, win32gui, win32con, os ,time
def middle(x,y):
    win32api.SetCursorPos((x,y))
    win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEDOWN,x,y,0,0)
    time.sleep(.02)
    win32api.mouse_event(win32con.MOUSEEVENTF_MIDDLEUP,x,y,0,0)
    time.sleep(.02)
def click(x,y):
    win32api.SetCursorPos((x,y)) # 0.02 ist das Minimum
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
    time.sleep(.02)
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def get_coords():
    x,y = win32api.GetCursorPos()
    print(x,y)
    return x,y
def setc(x,y):
    coords = x,y

    win32api.SetCursorPos(coords)
    
    time.sleep(.02)
c = 0
d = 0
i0 = input("your first spell: ")
i1 = input("your next spell: ")
i2 = input("your next spell: ")
i3 = input("your next spell: ")

print(i0)
while(1):
    a = win32api.GetAsyncKeyState(ord(i0))
    a1 = win32api.GetAsyncKeyState(ord(i1))
    a2 = win32api.GetAsyncKeyState(ord(i2))
    a3 = win32api.GetAsyncKeyState(ord(i3))
    
   # if a == -32768 or -32767:
    #    c = c+1
        
    #if a == 0:
     #   c = 0
   # if c == 1:
    #    gc = get_coords()
    #    gc0 = gc[0]
    #    gc1 = gc[1]
    #    middle(gc0,gc1)
    #    print("yes")
    if a or a1 or a2 or a3 == 0: 
        d = d+1

    if a or a1 or a2 or a3 != 0:
        d = 0
    if d == 1:
        gc = get_coords()
        gc0 = gc[0]
        gc1 = gc[1]
        click(gc0,gc1)
        print("click")
@Blackjack ich würde schon gerne einen Weg finden, wie man das in Python löst.
BlackJack

@zar1: Dann würde ich als erstes empfehlen Python zu lernen zusammen mit dem schreiben von lesbaren Quelltexten. Das weglassen der GUI macht den Quelltext nicht wesentlich besser.

Man bekommt das in Python nicht gelöst. Wenn Dir das Programm zu viele Ressourcen verbraucht, dann willst Du eine andere Programmiersprache verwenden.
zar1
User
Beiträge: 39
Registriert: Samstag 28. Dezember 2013, 01:08

sorry, dass ich dir da widersprechen muss aber ich find meinen quelltext ordentlich.

Import/Definitonen sind am Anfang des Quelltextes

und die Schleifen etc. unten. Was man daran als nicht lesbar definieren kann verstehe ich nicht ganz, zumal das,was ich hier gemacht habe, relativ logisch ist.

Das mit der anderen Programiersprache ist natürlich immer eine Möglichkeit.

Wenn du meinst dass ich nicht jede Zeile kommentiert habe, dann verstehe ich durchaus was du meinst, aber da ich es in erster Linie für mich geschrieben habe, hab ich das mit dem kommentieren weg gelassen und weil es jetzt nicht besonders schwer ist zu verstehen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@zar1: da wären zum einen doppelte Importe und mehrere in einer Zeile, fehlende oder zu viele Leerzeilen, durchnummerierte Variablennamen, Klammern um Bedingungen und eine 1 wo ein True hingehört.
Und die if-Abfragen zum Schluß sind nicht gerade einfach zu verstehen.

Zum Problem: Du willst nicht ständig den Status der Tasten prüfen, sondern über einen Hock auf Key-Events reagieren.
BlackJack

@zar1: Die Logik welche Importe in einer Zeile passieren und warum einige Module mehrfach importiert werden erschliesst sich mir nicht.

Die Funktionen am Anfang sind alle zusammengeklatscht ohne Leerzeichen dazwischen damit man besser sieht was da eigentlich zusammengehört. Ähnlich fehlen Leerzeichen um das ganze aufzulockern und leichter lesbar zu machen, zum Beispiel nach Kommas.

Die Funktionsnamen sind schlecht gewählt weil sie keine Tätigkeiten beschreiben auch sonst in der Regel nicht wirklich gut beschreiben was sie tun. `middle()` und `click()` sind fast identisch, das wäre also eigentlich *eine* Funktion die entsprechend parametrisiert werden müsste.

Der Kommentar ``# 0.02 ist das Minimum`` macht dort wo er steht überhaupt keinen Sinn.

`get_coords()` könnte man problemlos weglassen, oder einfach als ``get_coords = win32api.GetCursorPos`` definieren.

Bei `setc()` ist der abgekürzte Name unschön und warum *dort* jetzt ausgerechnet jede zweite Zeile eine Leerzeile ist…

Dann die ganzen tollen ein- bis zweibuchstabigen und durchnummerierten Namen — das ist Mist. Namen sollen dem Leser verraten was der Wert der dahinter steckt im Kontext des Programms bedeutet. `c`, `d`, `a1`, und Co tun das ganz sicher nicht. Bei durchnummerierten Namen will man in der Regel eine passende Datenstruktur verwenden. Meisten Listen.

Die Bedingungen in denen ``or`` vorkommt machen sicher nicht das was Du denkst. Das ist ein binärer Operator der einen der beiden Operanden als Ergebnis hat, und nicht das umgangssprachlice „oder”. ``a or b == c`` ist kein Test ob `a` gleich `c` ist oder `b` gleich `c` ist, sondern ob entweder `a` wahr ist, oder ``b == c`` wahr ist. Also mit Klammern: ``a or (b == c)``.

Dann dieses Umständliche `gc`, `gc0`, und `gc1`, wo Du doch offenslichtlich weisst wie man direkt einen Rückgabewert auf mehrere Namen verteilen kann. Dann auch bitte an was besseres als `gc0` und `gc1`. Zum Beispiel `x` und `y`.

Was da mit `c` und `d` in Abhängigkeit von den Bedingung passiert, sollte man besser kommentieren. Mir ist das jedenfalls unklar warum das so gemacht wird.

``while`` ist keine Funktion, also sollte man das auch nicht so schreiben.

Das Hauptprogramm auf Modulebene wäre besser in einer Funktion aufgehoben, konventionell `main()` genannt, die mit dem folgenden Idiom aufgerufen wird:

Code: Alles auswählen

if __name__ == '__main__':
    main()
Dann kann man das Modul sowohl ausführen, aber auch importieren ohne das die Funktion ausgeführt wird. Zum Beispiel um einzelne Funktionen interaktiv zu testen.

Es läuft letztlich darauf hinaus das man so gut wie jede Quelltextzeile anfassen muss wenn man das tatsächlich ordentlich machen will.
Antworten