Comment pdb de sortie de programme a commencé en eval () ou exec () sans montrer la sortie

StackOverflow https://stackoverflow.com/questions/3959418

  •  08-10-2019
  •  | 
  •  

Question

Dans mon code python Je cette ligne:

try:
    result = eval(command, self.globals, self.locals)
except SyntaxError:
    exec(command, self.globals, self.locals)

La variable command peut être une chaîne. D'où le débogueur python pdb peut être démarré en eval / exec et restent toujours actifs lorsque eval / exec est de retour. Ce que je veux faire est de vous assurer l'exécution du programme reprend son fonctionnement normal lors du retour de eval / exec. Pour vous donner une idée, c'est à peu près le comportement que je veux:

try:
    result = eval(command, self.globals, self.locals)
    try: self.globals['pdb'].run('continue')
    except: pass
except SyntaxError:
    exec(command, self.globals, self.locals)
    try: self.globals['pdb'].run('continue')
    except: pass

Cependant, la ligne de try est indiquée dans le débogueur avant qu'il ne soit exécuté, mais je ne veux pas que le débogueur pour montrer mon code du tout. En outre, il ne fonctionne pas vraiment ... La raison pour laquelle je le répète code est de minimiser le débogage dans mon code, sinon je pouvais le faire après le bloc except.

Comment puis-je faire?

En sidenote:

Si vous essayez d'entrer dans les lignes suivantes dans le IPython ou bpython interprètes vous verrez qu'ils ont le même problème et vous êtes en mesure d'entrer dans leur code.

import pdb
pdb.set_trace()
next

Toutefois, si vous le faites dans l'interpréteur norme CPython vous revenez à l'invite python. La raison est évidemment parce que les deux premiers sont mis en œuvre en python et le dernier n'est pas. Mais mon souhait est d'obtenir le même comportement, même quand tout le code est python.

Était-ce utile?

La solution

Alors que je suis un peu inquiet que vous êtes eval / exec'ing une chaîne que vous ne contrôlez pas, je vais vous assumez avez pensé que peu à travers.

Je pense que la chose la plus simple serait de persuader pdb de vérifier le cadre de la pile sur chaque étape et reprend automatiquement lorsque vous revenez au niveau souhaité. Vous pouvez le faire avec un simple morceau de hotfixing. Dans le code ci-dessous j'ai simplifié vers le bas à une simple eval car tout ce que vous demandez vraiment est d'avoir reprendre pdb automatiquement sur le retour à une fonction spécifique. Appel PDB () de resume_here (). Dans la fonction que vous ne voulez pas retracé. N.B. la reprise est mondiale et il n'y a qu'un seul point de reprise, mais je suis sûr que vous pouvez modifier que si vous vouliez.

Si vous exécutez le code, alors vous allez entrer dans le débogueur en fonction foo() et vous pouvez alors seule étape, mais dès que vous revenez à bar() le code continue automatiquement.

par exemple.

import sys
from pdb import Pdb

def trace_dispatch(self, frame, event, arg):
    if frame is self._resume_frame:
        self.set_continue()
        return
    return self._original_trace_dispatch(frame, event, arg)

def resume_here(self):
    Pdb._resume_frame = sys._getframe().f_back

# hotfix Pdb
Pdb._original_trace_dispatch = Pdb.trace_dispatch
Pdb.trace_dispatch = trace_dispatch
Pdb.resume_here = resume_here
Pdb._resume_frame = None

def foo():
    import pdb
    pdb.set_trace()
    print("tracing...")
    for i in range(3):
        print(i)

def bar():
    Pdb().resume_here()
    exec("foo();print('done')")
    print("returning")

bar()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top