Есть ли способ удалить созданные переменные, функции и т. Д. Из памяти интерпретатора?


115

Я уже пару дней искал точный ответ на этот вопрос, но ничего хорошего не нашел. Я не совсем новичок в программировании, но даже не на среднем уровне.

Когда я нахожусь в оболочке Python, я печатаю: dir()и я могу видеть все имена всех объектов в текущей области (основном блоке), их 6:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Затем, когда я, например x = 10, объявляю переменную, она автоматически добавляется к этому списку объектов во встроенном модуле dir(), а когда я dir()снова набираю текст, теперь отображается:

['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'x']

То же самое и с функциями, классами и т. Д.

Как мне удалить все эти новые объекты, не стирая стандартные 6, которые были доступны в начале?

Я читал здесь про «очистку памяти», «очистку консоли», которая стирает весь текст из окна командной строки:

>>> import sys
>>> clear = lambda: os.system('cls')
>>> clear()

Но все это не имеет ничего общего с тем, чего я пытаюсь достичь, это не очищает все используемые объекты.


2
Почему вы считаете, что вам нужно это сделать, или вы просто спрашиваете из любопытства?
PM 2Ring

Я просто не знал, что там есть delфункция. Я начинаю изучать Python, и мне часто приходится экспериментировать в оболочке, поэтому стандартные имена переменных, такие как xили yчасто уже используются, а перезапуск оболочки занимает еще 15 секунд (у меня сейчас очень, очень старый ноутбук). Поэтому я хотел найти способ быстрее очистить память Python.
фунгхорн

1
Ах. FWIW del- это не совсем функция, поэтому нет (и ). Это ключевое слово вводит оператор del. Конечно, то, как он на самом деле удаляет объект, может включать функции, но это уже другая история ...
PM 2Ring

При экспериментировании с оболочкой имена вроде xили yне должны использоваться, если вы их не используете. Или, если вы не сделаете что-нибудь глупое from _somemodule_ import *, вы получите все виды мусора, захламляющего место. :)
PM 2Ring

1
Я искал этот вопрос в Google, и теперь мне интересно - почему я не могу просто перезапустить ядро ​​и повторно запустить скрипт сверху, если я все равно хочу удалить все переменные и функции?
vagabond

Ответы:


160

Вы можете удалить отдельные имена с помощью del:

del x

или вы можете удалить их с globals()объекта:

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

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

Модули, которые вы импортировали ( import os), останутся импортированными, потому что на них ссылается sys.modules; последующий импорт будет повторно использовать уже импортированный объект модуля. У вас просто не будет ссылки на них в вашем текущем глобальном пространстве имен.


Что ж, должен сказать, startswith('_')кажется довольно наивным. Если кто-то достаточно умен, чтобы писать _foo=42или даже __foo__=42, как мы можем их удалить? Есть ли способ получить имена стандартных свойств модуля программно?
georg

2
@georg: Я закодировал цикл в целях защиты. Вам придется жестко запрограммировать начальный список имен, чтобы сохранить его, если вы хотите добиться большего.
Мартин Питерс

Значит, никак? Моя мысль была dir(ModuleType()), но она только возвращается docи name.
georg

1
@georg: нет; глобальное пространство имен интерпретатора также меняется от выпуска к выпуску, и нет надежного способа (о котором я знаю) перечислить то, что было там, когда вы открыли интерпретатор на более позднем этапе .
Мартин Питерс

1
Функции и классы @nakE - это такие же объекты, как и любые другие. Они не особенные; используйте белый список или проверьте тип объекта, который вам нужен для сохранения классов и функций.
Мартейн Питерс

67

Да. Есть простой способ удалить все в iPython. В консоли iPython просто введите:

%reset

Затем система попросит вас подтвердить. Нажмите y. Если вы не хотите видеть это приглашение, просто введите:

%reset -f

Это должно работать ..


1
Еще раз, почему это не лучший ответ?
myradio

12
@myradio Потому что это не имеет значения для всех, кто не использует IPython , и не отвечает на вопрос; вопрос спрашивает, как удалить ссылки на глобальные объекты, а не сбросить содержимое оболочки IPython .
Андреас

17

Вы можете использовать сборщик мусора Python:

import gc
gc.collect()

6
Привет @Fardin! Спасибо! Ваш ответ помог мне и спас мне день! Но до gc.collect () я использовал del (переменную).
Gmosy Gnaq

9

Если вы находитесь в интерактивной среде, например, Jupyterили ipythonвам может быть интересно удалить ненужные var, если они становятся тяжелыми.

Магические команды reset и reset_selectiveдоступны в интерактивных сеансах Python, таких как ipythonиJupyter

1) reset

reset Сбрасывает пространство имен, удаляя все имена, определенные пользователем, если вызывается без аргументов.

inа outпараметры указывают, хотите ли вы очистить кеши ввода / вывода. История каталогов сбрасывается с dhistпараметром.

reset in out

Еще один интересный момент заключается в arrayтом, что удаляет только массивы numpy:

reset array

2) reset_selective

Сбрасывает пространство имен, удаляя имена, определенные пользователем. История ввода / вывода остается на тот случай, если они вам понадобятся.

Пример чистого массива:

In [1]: import numpy as np
In [2]: littleArray = np.array([1,2,3,4,5])
In [3]: who_ls
Out[3]: ['littleArray', 'np']
In [4]: reset_selective -f littleArray
In [5]: who_ls
Out[5]: ['np']

Источник: http://ipython.readthedocs.io/en/stable/interactive/magics.html


6

Это сработало для меня.

Вам нужно запустить его дважды, один раз для глобальных, за которыми следуют локальные

for name in dir():
    if not name.startswith('_'):
        del globals()[name]

for name in dir():
    if not name.startswith('_'):
        del locals()[name]

4

На самом деле python будет освобождать память, которая больше не используется. Это называется сборкой мусора, которая в Python является автоматическим процессом. Но все же, если вы хотите это сделать, вы можете удалить его с помощью del variable_name. Вы также можете сделать это, присвоив переменнойNone

a = 10
print a 

del a       
print a      ## throws an error here because it's been deleted already.

Единственный способ по-настоящему освободить память от объектов Python, на которые нет ссылок, - это использовать сборщик мусора. Ключевое слово del просто отвязывает имя от объекта, но объект по-прежнему необходимо собрать мусором. Вы можете принудительно запустить сборщик мусора с помощью модуля gc, но это почти наверняка преждевременная оптимизация, но она имеет свои риски. Использование delне имеет реального эффекта, поскольку эти имена в любом случае были бы удалены, поскольку они вышли из области видимости.


На самом деле. Конечно, при работе в глобальном пространстве имен интерпретатора имена не выходят за пределы области видимости, но что с того. :) Думаю, также стоит упомянуть, что то, что происходит с памятью, используемой объектами, которые были собраны мусором, зависит от реализации, но в большинстве реализаций Python память gc'ed просто возвращается в пул Python, она не возвращается в пул ОС до выхода из программы.
PM 2Ring,

@ PM2Ring LOL :) Думаю, да. Откуда вы ссылаетесь на Python?
d-coder

2
Обратите внимание, что в CPython сборщик мусора нужен только для прерывания ссылочных циклов. Если нет ссылки остается, объект является Insta-удаляется из памяти. Так del что здесь есть реальный эффект.
Мартейн Питерс

@MartijnPieters, мгновенно удалено? Это технический термин? :)
Eryk Sun

2
@eryksun: да, конечно в соответствии с RFC 4042-bis2! :-P
Martijn Pieters
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.