Frage

Ich schreibe ein Spiel-Engine mit pygame und box2d, und im Charakter-Builder, ich möchte den Code schreiben können, die auf keydown Ereignisse ausgeführt werden.

Mein Plan war, einen Texteditor, in dem Zeichen Builder hat, dass Sie ähnlich Code schreiben lassen zu:

if key == K_a:
    ## Move left
    pass
elif key == K_d:
    ## Move right
    pass

Ich werde den Inhalt des Texteditors als String abrufen, und ich mag der Code in einem Verfahren, bei dieser Methode der Zeichen ausgeführt werden:

def keydown(self, key):
    ## Run code from text editor

Was ist der beste Weg, das zu tun?

War es hilfreich?

Lösung

Sie können über die eval(string) Methode, dies zu tun.

Definition

eval(code, globals=None, locals=None)
Der Code ist nur Standard-Python-Code - dies bedeutet, dass es muss noch richtig eingerückt werden.

Die Globals können eine benutzerdefinierte __builtins__ definiert haben, die für Sicherungszwecke nützlich sein könnte.

Beispiel

eval("print('Hello')")

Möchten hello an die Konsole drucken. Sie können auch lokale und globale Variablen angeben, für den Code zu verwenden:

eval("print('Hello, %s'%name)", {}, {'name':'person-b'})

Sicherheitsbedenken

Seien Sie vorsichtig, wenn. Alle Benutzereingaben werden ausgeführt. Bedenken Sie:

eval("import os;os.system('sudo rm -rf /')")

Es gibt eine Reihe von Möglichkeiten, um die. Am einfachsten ist es, etwas zu tun wie:

eval("import os;...", {'os':None})

, die eine Ausnahme werfen, anstatt die Festplatte zu löschen. Während Ihr Programm Desktop ist, könnte dies ein Problem sein, wenn die Menschen Skripte neu verteilt, die ich bestimmt vorstellen wird.

Seltsames Beispiel

Hier ist ein Beispiel für die Verwendung eval eher seltsam:

def hello() : print('Hello')
def world() : print('world')
CURRENT_MOOD = 'happy'

eval(get_code(), {'contrivedExample':__main__}, {'hi':hello}.update(locals()))

Was das bedeutet auf der eval Linie ist:

  1. Gibt das aktuelle Modul einen anderen Namen (es contrivedExample an das Skript wird). Der Verbraucher kann contrivedExample.hello() call now.)
  2. Sie definiert hi als hello zeigen
  3. Es kombiniert das Wörterbuch mit der Liste der aktuellen Globals im Vollstreckungs Modul.

FAIL

Es stellt sich heraus (durch commen!), Die Sie tatsächlich die exec Anweisung verwenden müssen. Big oops. Die überarbeiteten Beispiele sind wie folgt:


exec Definition

(Das kommt mir bekannt vor!) Exec ist eine Aussage:
exec "code" [in scope] Wo Umfang ist ein Wörterbuch der lokalen und globalen Variablen. Wenn dies nicht angegeben ist, führt er im aktuellen Bereich.

Der Code ist nur Standard-Python-Code - das bedeutet, dass es immer noch richtig eingerückt sein muss.

exec Beispiel

exec "print('hello')"

Möchten hello an die Konsole drucken. Sie können auch lokale und globale Variablen angeben, für den Code zu verwenden:

eval "print('hello, '+name)" in {'name':'person-b'}

exec Sicherheitsbedenken

Seien Sie vorsichtig, wenn. Alle Benutzereingaben werden ausgeführt. Bedenken Sie:

exec "import os;os.system('sudo rm -rf /')"

Drucken Statement

Wie auch durch commen erwähnt, print ist eine Aussage in allen Versionen von Python vor 3,0. In 2.6 kann das Verhalten durch die Eingabe from __future__ import print_statement geändert werden. Andernfalls Verwendung:

print "hello"

Statt:

print("hello")

Andere Tipps

Wie andere haben darauf hingewiesen, können Sie den Text in einen String und Verwendung exec "codestring" laden kann. Wenn bereits in einer Datei enthalten sind, unter Verwendung von execfile wird vermeiden, dass es zu laden.

Eine Leistung Hinweis: Sie sollten execing den Code mehrfach, wie Parsing vermeiden und den Python-Source Kompilieren ein langsamer Prozess ist. dh. nicht haben:

def keydown(self, key):
    exec user_code

können Sie verbessern das ein wenig von der Quelle in einen Code Objekt kompiliert (mit compile() und exec das, oder besser, durch eine Funktion erstellt, die Sie um zu halten, und nur einmal bauen. Entweder muss den Benutzer schreiben „def my_handler (args ...)“oder voranstellen, es sich selbst, und so etwas wie:

user_source = "def user_func(args):\n" + '\n'.join("    "+line for line in user_source.splitlines())

d={}
exec user_source in d
user_func = d['user_func']

Dann später:

if key == K_a:
   user_func(args)

Sie können mit eval()

eval oder exec. Sie sollten auf jeden Fall Python-Bibliothek Referenz vor der Programmierung lesen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top