Чи є спосіб видалити створені змінні, функції тощо з пам'яті перекладача?


114

Я шукав точну відповідь на це питання вже пару днів, але нічого доброго не отримав. Я не повний початківець у програмуванні, але ще не проміжний рівень.

Коли я перебуваю в оболонці 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.
funghorn

1
Ага. FWIW, delне є точно функцією, отже, ні (і ). Це ключове слово, яке вводить вираз del. Звичайно, як він насправді видаляє об’єкт, це може включати функції, але це вже інша історія ...
PM 2Ring

Експериментуючи з оболонками, імена на кшталт xабо yне повинні використовуватись, якщо ви їх не використовуєте. Або якщо ви не зробите щось подібне нерозумно from _somemodule_ import *, то ви отримаєте всіляке сміття, що забиває місце. :)
PM 2Ring

1
Я перейшов до цього питання, і тепер мені цікаво - чому я не можу просто перезапустити ядро ​​і запустити сценарій зверху, якщо я хочу видалити всі змінні та функції?
бродяга

Відповіді:


159

Можна видалити окремі імена за допомогою 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: Я захищав цикл захисно. Вам доведеться жорстко кодувати початковий список імен, який потрібно зберегти, якщо ви хочете зробити краще.
Martijn Pieters

Отже, ніяк? Моя думка була dir(ModuleType()), але вона лише повертається docі name.
georg

1
@georg: nope; глобальний простір імен інтерпретатора змінюється також від випуску до випуску, і не існує надійного способу (про який я знаю) перерахувати, що було там, коли ви відкрили перекладача на більш пізньому етапі .
Martijn Pieters

1
Функції та класи @nakE - це просто об'єкти, як і будь-які інші. Вони не особливі; використовувати білий список або перевірити потрібний вам тип об'єкта для збереження класів та функцій.
Martijn Pieters

67

Так. Існує простий спосіб видалити все з iPython. У консолі iPython просто введіть:

%reset

Тоді система попросить вас підтвердити. Натисніть y. Якщо ви не хочете бачити це запит, просто введіть:

%reset -f

Це має працювати.


1
Знову ж таки, чому це не найкраща відповідь?
myradio

11
@myradio Оскільки це не має значення для всіх, хто не використовує IPython , і він не відповідає на питання; у запитанні задається питання, як видалити глобальні посилання на об'єкти, а не скинути вміст оболонки IPython .
Андреас

17

Ви можете використовувати пітон-збирач сміття:

import gc
gc.collect()

6
Привіт @Fardin! Дякую! Ваша відповідь зробила роботу і врятувала мені день! Але перед gc.collect () я зробив del (змінний).
Gmosy Gnaq

9

Якщо ви перебуваєте в такому інтерактивному середовищі, Jupyterабо ipythonвам може бути цікаво очистити небажані варси, якщо вони важкі.

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

1) reset

reset Скидає простір імен, видаляючи всі імена, визначені користувачем, якщо вони викликаються без аргументів.

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

reset in out

Ще один цікавий варіант - це arrayте, що видаляє лише рясні масиви:

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 :) Я так думаю. Звідки ви звертаєтесь до пітона?
d-coder

2
Зауважте, що в CPython GC потрібен лише для розбиття еталонних циклів. Якщо немає посилання залишається, об'єкт є Insta-видаляється з пам'яті. Так del само є реальний ефект тут.
Martijn Pieters

@MartijnPieters, встановити-видалити? Це технічний термін? :)
Ерік Нд

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