Как очистить все переменные в середине скрипта Python?

88

Я ищу что-то похожее на «очистить» в Matlab: команду / функцию, которая удаляет все переменные из рабочей области, освобождая их из системной памяти. Есть ли такое в Python?

EDIT: я хочу написать сценарий, который в какой-то момент очищает все переменные.

змея
источник
2
Будет полезно, если вы измените заголовок на что-то вроде «Как очистить все переменные в середине сценария Python?» для будущих поисков по теме, потому что "Как перезапустить командное окно в Python?" не имеет ничего общего с тем, о чем вы на самом деле спрашиваете.
Сэм Долан,
Можете ли вы представить какой-либо возможный контекст, в котором это имеет смысл?
S.Lott
2
Похоже на еще один случай попытки перенести привычки кодирования из их родной среды в ту, где они не имеют никакого смысла.
Гленн Мейнард
Если вас беспокоят только массивные объекты (изображения или другие огромные массивы), вы можете сделать delэто, когда закончите. Если вы просто беспокоитесь о загромождении пространства имен, вам, вероятно, следует пересмотреть свой дизайн, используя такое количество имен. Например, для серии преобразований изображения сохранение каждого промежуточного шага, вероятно, не нужно.
Nick T
4
@ S.Lott: исследовательский научный анализ в консоли. Часто в конечном итоге получается много нежелательных переменных (после того, как мы попробовали что-то, а затем решили, что это не подходящий путь). Но в данном случае ответ Джона Ла Роя является наиболее подходящим.
naught101

Ответы:

70

Следующая последовательность команд удаляет все имена из текущего модуля:

>>> import sys
>>> sys.modules[__name__].__dict__.clear()

Я сомневаюсь, что вы действительно хотите этого, потому что "каждое имя" включает в себя все встроенные модули, поэтому после такого полного уничтожения вы мало что сможете сделать. Помните, что в Python на самом деле нет такой вещи, как «переменная» - есть объекты многих видов (включая модули, функции, классы, числа, строки и т. Д.), И есть имена , привязанные к объектам; Последовательность удаляет каждое имя из модуля (соответствующие объекты удаляются тогда и только тогда, когда каждая ссылка на них была только что удалена).

Может быть, вы хотите быть более избирательным, но вам сложно угадать, что именно вы имеете в виду, если только вы не хотите быть более конкретным. Но просто чтобы привести пример:

>>> import sys
>>> this = sys.modules[__name__]
>>> for n in dir():
...   if n[0]!='_': delattr(this, n)
... 
>>>

Эта последовательность оставляет в покое имена, которые являются личными или магическими, включая __builtins__специальное имя, в котором находятся все встроенные имена. Итак, встроенные модули по-прежнему работают - например:

>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'n']
>>> 

Как видите, имя n(в нем управляющая переменная for) также остается (поскольку оно повторно привязывается в forпредложении каждый раз), поэтому, возможно, было бы лучше назвать эту управляющую переменную _, например, чтобы четко показать «это special "(плюс, в интерактивном интерпретаторе имя в _любом случае повторно привязывается после каждого полного выражения, введенного в подсказке, к значению этого выражения, поэтому оно не останется в памяти надолго ;-).

Во всяком случае, как только вы определили , что именно это является вы хотите сделать, это не трудно определить функцию для этой цели и положить его в файл для запуска (если вы хотите его только в интерактивных сессиях) или файл сайт-подгоняет ( если вы хотите это в каждом скрипте).

Алекс Мартелли
источник
2
Что ж, вы всегда можете сохранить копию исходного словаря при запуске, а затем удалить добавленные имена;) Однако я думаю, что это явное злоупотребление динамической системой, и я не могу придумать бессмысленную ситуацию, чтобы сделать это в.
monoceres
5
Ха-ха, это великолепно ... Удивительно, как много функциональности вы теряете, делая это, и, тем не менее, сколько функциональности вы можете вернуть, делая что-то вроде int = (2).__class__, str = ''.__class__и True = (1 == 1)т.д ...
Чинмей Канчи,
@monoceres, как бы вы назвали эту копию и где бы вы ее спрятали, чтобы ее тоже не стерли? -)
Алекс Мартелли
2
Чем больше я использую Python, тем больше мне он нравится. Мало того, что это отличный язык, вы также можете часами просто возиться с ним и заставлять его делать вещи, которые вам действительно не следует ;-)
Чинмай Канчи
1
Возможно, я ошибся, но столкнулся с одной проблемой: когда вы используете for n in dir(): ... if n[0]!='_': delattr(this, n)в какой-то момент, n=thisа вы удаляете его в цикле! Итак, на следующей итерации вы получите ошибку при попытке, delattr(this,n)потому что вы только что удалили ее! :) Так что не работает правильно
Mikhail_Sam
59

Нет, вам лучше перезапустить интерпретатор

IPython - отличная замена встроенному интерпретатору и имеет %resetкоманду, которая обычно работает

Джон Ла Рой
источник
1
Под «Нет» вы имеете в виду, что я не должен этого делать или это невозможно? Если вы скажете, что я не должен этого делать, не могли бы вы объяснить, почему?
snakile
6
+1: Мне нужно меньше четверти секунды, чтобы ctrl-dзатем pyt-> tabвернуться в интерпретатор. Нет причин делать здесь что-то особенное.
Сэм Долан,
3
% reset работает для большинства переменных, для некоторых - нет. Для меня только перезапуск интерпретатора гарантирует очистку всего.
artemis_clyde
3
Используется, %reset -fчтобы быть не интерактивным. stackoverflow.com/questions/38798181/…
Иоахим Вагнер
28

Если вы напишете функцию, то, как только вы ее оставите, все имена внутри исчезнут.

Эта концепция называется пространством имен, и она настолько хороша, что вошла в дзен Python :

Пространства имен - одна отличная идея - давайте сделаем их больше!

Пространство имен IPython также можно сбросить с помощью волшебной команды %reset -f. (Это -fозначает «сила»; другими словами, «не спрашивайте меня, действительно ли я хочу удалить все переменные, просто сделайте это».)

Йохен Ритцель
источник
1
Я добавлю очевидное: если вы поместите все в основную функцию (включая импорт), вы на практике получите рабочее место, которое можно сбросить, просто выйдя из этой функции. Я считаю, что вопрос был задан именно для этого.
Дэвид
8
from IPython import get_ipython;   
get_ipython().magic('reset -sf')
Анураг Гупта
источник
3
Пожалуйста, посмотрите, как ответить
Адонис
1
или просто%reset -sf
Bal Krishna Jha
1
на самом деле команда% reset -sf не работает и выдает ошибку, когда вы запускаете свой скрипт python с приглашением anaconda (даже если вы использовали try- except; он не работает). Вы можете попробовать то же самое, и вы увидите. Но использование библиотеки ipython решит эту проблему во всех возможных случаях.
Анураг Гупта
5

Это модифицированная версия ответа Алекса. Мы можем сохранить состояние пространства имен модуля и восстановить его, используя следующие 2 метода ...

__saved_context__ = {}

def saveContext():
    import sys
    __saved_context__.update(sys.modules[__name__].__dict__)

def restoreContext():
    import sys
    names = sys.modules[__name__].__dict__.keys()
    for n in names:
        if n not in __saved_context__:
            del sys.modules[__name__].__dict__[n]

saveContext()

hello = 'hi there'
print hello             # prints "hi there" on stdout

restoreContext()

print hello             # throws an exception

Вы также можете добавить строку «clear = restoreContext» перед вызовом saveContext (), и clear () будет работать как clear в Matlab.

Кувшин
источник
1
Отличный ответ! Я считаю, что для Python 3 вы захотите настроить restoreContext names = list(sys.modules[__name__].__dict__.keys()), иначе Python будет жаловаться, что вы изменили размер словаря во время итерации по его dict_keysобъекту.
Сэм Бейдер
Кроме того, для тех, кто хочет получить importэтот ответ (т.е. я сохранил его и импортирую из записной книжки Jupyter, чтобы очистить пространство имен между различными проблемами в домашнем задании), я думаю, вы захотите использовать "__main__"вместо __name__.
Сэм Бейдер,
3

В Spyder можно настроить консоль IPython для каждого файла Python, чтобы очищать все переменные перед каждым выполнением в меню Run -> Configuration -> General settings -> Remove all variables before execution.

тардис
источник
2

globals()Функция возвращает словарь, где ключи являются именами объектов , которые вы можете назвать (и ценность, кстати, является ids этих объектов) exec()функция принимает строку и выполняет ее , как если бы вы просто наберите в консоли питона. Итак, код

for i in list(globals().keys()):
    if(i[0] != '_'):
        exec('del {}'.format(i))
Колай.Не
источник
Хотя этот фрагмент кода может решить вопрос, в том числе объяснение помогает улучшить качество вашего ответа. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода.
Стефан Крейн
Спасибо. Сейчас лучше?
Kolay.Ne 02
0

В простаивающей IDE есть Shell / Restart Shell. Cntrl-F6 сделает это.

Гарольд Хенсон
источник
0

Разве это не самый простой способ создать класс, содержащий все необходимые переменные? Тогда у вас есть один объект со всеми переменными curretn, и если вам нужно, вы можете перезаписать эту переменную?

Иван
источник