Как экспортировать переменную из PDB?

Представьте себе следующий сценарий: скрипт запускается из оболочки IPython и в точке останова вызывается отладчик python. Используя команды PDB, на этом этапе можно проанализировать код и переменные. Но часто оказывается, что значения переменных требуют более глубокого исследования.

Можно ли экспортировать значение переменной в оболочку IPython?

Мой конкретный вариант использования: я борюсь с довольно огромным массивом numpy, который, похоже, не имеет правильных значений. Я знаю, что могу запускать любые команды Python из отладчика Python, но было бы полезно сохранить значения переменной в разных точках останова и использовать их все в оболочке IPython. Я представляю что-то вроде

ipdb> global var1; var1 = var
ipdb> continue
...
ipdb> global var2; var2 = var
ipdb> continue
... 
In [2]: abs(var1 - var2) # do some interesting calculations with IPython

person lumbric    schedule 13.02.2013    source источник
comment


Ответы (3)


Вы можете использовать глобальные():

ipdb>__name__
'my_module'
ipdb> get_var = 'a value'
ipdb> globals()['myvar'] = get_var
ipdb> q
In [11]: my_module.myvar
Out[11]: 'a value'

Это предполагает, что точка останова установлена ​​в my_module.py, поэтому мы редактируем глобальные переменные модуля my_module.

person chespinoza    schedule 13.02.2013
comment
Это не работает, но я не уверен, почему. Я получаю 'myz' is not defined. - person lumbric; 14.02.2013
comment
@lumbric как ты это делаешь? - person chespinoza; 14.02.2013
comment
Я думаю, что это не сработало, потому что myvar скорее всего живет в другом модуле, а не непосредственно в IPython. Я отредактировал ваш ответ, чтобы уточнить. Пожалуйста, проверьте, правильно ли это! - person lumbric; 24.03.2015
comment
Вместо использования globals() вы можете просто импортировать любой модуль и присвоить переменную полю в этом модуле. Это было проще для меня. - person John Lehmann; 14.10.2017
comment
import sys, затем sys.modules['__main__'].myvar = get_var - person Brent Baccala; 25.06.2019

Не красивое решение, но работающее:

ipdb> import cPickle; f=open('/tmp/dump1','w+'); cPickle.dump(var,f); f.close()

...

ipdb> import cPickle; f=open('/tmp/dump2','w+'); cPickle.dump(var,f); f.close()

тогда

In [2]: var1 = cPickle.load(open('/tmp/dump1'))
In [3]: var2 = cPickle.load(open('/tmp/dump2'))
person sega_sai    schedule 13.02.2013

Вам нужно различать разные globals().
Например, предположим, что у нас есть модуль: mymodule.py

foo = 100
def test():
    bar = 200
    return bar

Мы запускаем его под контролем pdb.

>>> import pdb
>>> import mymodule
>>> foobar = 300
>>> pdb.run('mymodule.test()')
> <string>(1)<module>()
(Pdb) print foobar
300
(Pdb) print foo
*** NameError: name 'foo' is not defined
(Pdb) global foobar2; foobar2 = 301
(Pdb) print foobar2
301

В начале, а именно перед выполнением test(), окружение в pdb - это ваше текущее globals(). Таким образом, foobar определено, а foo не определено.
Затем мы выполняем test() и останавливаемся в конце bar = 200.

-> bar = 200
(Pdb) print bar
200
(Pdb) print foo
100
(Pdb) print foobar
*** NameError: name 'foobar' is not defined
(Pdb) global foo2; foo2 = 101
(Pdb) print foo2
101
(Pdb) c
>>> 

Окружение в pdb было изменено. Он использует globals() mymodule в test(). Таким образом определяется 'foobaris not defined. whilefoo`.

Мы экспортировали две переменные foobar2 и foo2. Но живут они в разных масштабах.

>>> foobar2
301
>>> mymodule.foobar2

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    mymodule.foobar2
AttributeError: 'module' object has no attribute 'foobar2'
>>> mymodule.foo2
101
>>> foo2

Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    foo2
NameError: name 'foo2' is not defined

Вы уже нашли решение. Но это работает немного по-другому.

person nymk    schedule 13.02.2013