2016-05-04 8 views
2

Ich habe ein paar Zeilen Code, die ich über exec() ausführen muss und ich würde gerne wissen, welche Zeile ZeroDivisionError steigt.Ho die Argumente eines ZeroDivisionError abfangen, die über exec() ausgeführt werden?

Hier ein Beispiel:

code = \ 
''' 
a = 9 
b = 0 
c = a/b 
print(c) 
''' 
>>>exec(code) 
--------------------------------------------------------------------------- 
ZeroDivisionError       Traceback (most recent call last) 
<ipython-input-3-00bada8e7a44> in <module>() 
     5 print(c) 
     6 ''' 
----> 7 exec(code) 

<string> in <module>() 

ZeroDivisionError: division by zero 

Das ist in Ordnung, aber ich möchte c = a/b statt exec(code) als Argument der Ausnahme haben, wie es für andere Arten von Fehler tritt auf:

code = \ 
''' 
a = 9 
b = 0 
c === b 
print(c) 
''' 
>>>exec(code) 
    File "<string>", line 4 
    c === b 
     ^
SyntaxError: invalid syntax 

In diesem Fall zeigt SyntaxError direkt auf die Zeile, die für den Fehler verantwortlich ist.

Warum dieser Unterschied? Wie kann ich ZeroDivisionError richtig angezeigt bekommen?

UPDATE

Ich habe die „compile() Lösung“ von Schore vorgeschlagen versucht, aber es hat nicht funktioniert, wie in meinem Fall erwartet:

code = \ 
''' 
a = 9 
b = 0 
c = a/b 
print(c) 
''' 
z = compile(code, "", "exec") 
>>>exec(z) 
ZeroDivisionError       Traceback (most recent call last) 
<ipython-input-8-857f94e79b67> in <module>() 
     6 ''' 
     7 z = compile(code, "", "exec") 
----> 8 exec(z) 

? in <module>() 

ZeroDivisionError: division by zero 
+0

Ich nehme an, dass Sie vollständig verstehen, dass 'exec' (und' eval') ein [Sicherheitsrisiko] sein kann (http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html), und dass Sie einen Weg haben um zu verhindern, dass gefährlicher Code "ausgeführt" wird ... –

+0

Ja, ich weiß, ich habe Sicherheitsüberprüfung des Codes und bis jetzt ist es nur für Code-Schnipsel, die ich geschrieben habe, also sollte es in Ordnung sein. –

Antwort

2

Der Grund dafür ist, dass die Nullteilungsfehler ist ein Laufzeitfehler und der === ist ein 'Compiler' Art von Fehler (gut, für Python wird es gefunden, wenn der === in Computer Anweisungen umgewandelt wird, hat es nicht wirklich einen Compiler).

Was Sie tun können, um die richtige Zeile des Fehlers zu erhalten, besteht darin, den Code in separate Zeilen aufzuteilen und sie nacheinander auszuführen (mit einer Schleife) und die Zeile zu drucken, die die Ausnahme verursacht.

+1

Ich habe über eine solche Lösung nachgedacht. Ich wollte prüfen, ob ein besserer Weg möglich ist, da ich den Code nicht in Zeilen aufteilen muss, sondern für diesen speziellen Fall. Natürlich, wenn es keine andere Möglichkeit gibt, werde ich es tun. –

+1

FWIW, obwohl der Standard-CPython-Interpreter den Python-Quellcode nicht mit dem Maschinencode Ihrer CPU kompiliert, kompiliert er ihn in Python-Bytecode, der effektiv der Maschinencode eines virtuellen Python-Rechners ist. Und es hat eine "compile" -Funktion, die verwendet werden kann, um explizit Code zu kompilieren, den Sie an 'exec' übergeben möchten. Siehe http://stackoverflow.com/questions/2220699/whats-the-difference-between-eval-exec-and-compile-in-python für einige interessante Informationen. –

1

Sie Kompilierung verwenden:

>>> code = \ 
... ''' 
... a = 9 
... b = 0 
... c = a/b 
... print(c) 
... ''' 
>>> c = compile(code, "", "exec") 
>>> exec(c) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "", line 4, in <module> 

ZeroDivisionError: integer division or modulo by zero 

diese Weise können Sie die Zeilennummer erhalten, ohne den Code splitten.

+0

Ich bekomme die Zeilennummer in der Fehlermeldung nicht ... –

+0

Möglicherweise ist dieses Verhalten spezifisch für Ihre Python-Umgebung. Sie sollten Michel Keijzers Antwort versuchen, da sein Ansatz überall funktioniert. Den Code zu teilen und Zeile für Zeile auszuführen, ist nicht so hässlich ... – Schore

+0

Ich werde bis morgen warten, dann werde ich dafür gehen, wenn nichts anderes verfügbar ist. Ich habe darüber nachgedacht, die ZeroDivisionError-Klasse zu refaktorieren oder eine spezielle Klasse für solche Fälle zu erstellen. Aber ich habe keinen Willen, es jetzt zu tun ... –