Yorumlayıcının belleğinden oluşturulan değişkenleri, işlevleri vb. Silmenin bir yolu var mı?


114

Birkaç gündür bu soruya doğru cevabı arıyordum ama iyi bir şey bulamadım. Programlama konusunda tam bir başlangıç ​​değilim, ancak henüz orta düzeyde bile değilim.

Python'un kabuğundayken şunu yazıyorum: dir()ve mevcut kapsamdaki (ana blok) tüm nesnelerin tüm adlarını görebiliyorum, bunlardan 6 tane var:

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

Sonra, örneğin bir değişken x = 10bildirdiğimde, yerleşik modül altındaki nesne listelerine otomatik olarak ekler dir()ve dir()tekrar yazdığımda , şimdi şunu gösterir:

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

Aynısı işlevler, sınıflar vb. İçin de geçerlidir.

Başlangıçta mevcut olan standart 6'yı silmeden tüm bu yeni nesneleri nasıl silebilirim?

Komut istemi penceresinden tüm metni silen "bellek temizleme", "konsolun temizlenmesi" hakkında burada okudum:

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

Ancak tüm bunların başarmaya çalıştığım şeyle hiçbir ilgisi yok, kullanılmış tüm nesneleri temizlemiyor.


2
Neden bunu yapmanız gerektiğini düşünüyorsunuz yoksa sadece meraktan mı soruyorsunuz?
PM 2Ring

Sadece orada bir delişlev olduğunu bilmiyordum . Ben Python öğrenmek ve sık sık kabuğunda deneme yapmanız, gibi pek standart değişken adları başlıyorum xya yzaten kullanımda sıklıkla ve kabuk yeniden başlatmadan (şimdi bir çok, çok eski laptop) yapmak için başka bir 15 saniye sürer. Bu yüzden Python belleğini daha hızlı temizlemenin bir yolunu bulmak istedim.
funghorn

1
Ah. FWIW, deltam olarak bir işlev değildir, dolayısıyla hayır (ve ). Bir del ifadesi sunan bir anahtar kelimedir. Elbette, bir nesnenin aslında nasıl silindiğini gösteren işlevler olabilir, ancak bu başka bir hikaye ...
PM 2Ring

Gibi kabuk adlarında denemeler yaparken xveya ysürece kullanımda olmamalıdır sen bunları kullanıyor. Ya da aptalca bir şey yapmazsanız from _somemodule_ import *, o zaman her tür çöpün etrafa dağılmasına neden olursunuz. :)
PM 2Ring

1
Google'da bu soruya giden yolu araştırdım ve şimdi merak ediyorum - tüm değişkenleri ve işlevleri yine de silmek istiyorsam neden çekirdeği yeniden başlatıp komut dosyasını en baştan tekrar çalıştıramıyorum?
serseri

Yanıtlar:


159

Tek tek isimleri silebilirsiniz del:

del x

veya bunları globals()nesneden kaldırabilirsiniz :

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

Bu sadece örnek bir döngüdür; sadece alt çizgi ile başlamayan isimleri savunma amaçlı olarak siler ve çevirmeninizin başında sadece alt çizgi olmayan isimleri kullandığınız (mantıksız değil) varsayımını yapar. Gerçekten eksiksiz olmak istiyorsanız, saklamak için (beyaz liste) sabit kodlanmış bir isim listesi kullanabilirsiniz. Yorumlayıcıdan çıkıp yeniden başlatmak dışında, temizlemeyi sizin için yapacak yerleşik bir işlev yoktur.

İçe aktardığınız modüller ( import os), tarafından referans verildiği için içe aktarılmış olarak kalacaktır sys.modules; sonraki içe aktarmalar, önceden alınmış modül nesnesini yeniden kullanacaktır. Mevcut global ad alanınızda bunlara bir referansınız olmayacak.


Şey, startswith('_')oldukça saf göründüğünü söylemeliyim . Birisi yazacak kadar akıllıysa, _foo=42hatta __foo__=42bunları nasıl silebiliriz? Standart modül özelliklerinin adlarını programlı olarak almanın bir yolu var mı?
georg

2
@georg: Döngüyü savunma amaçlı kodladım. Daha iyisini yapmak istiyorsanız, saklamak için bir ilk isim listesini kodlamanız gerekecek.
Martijn Pieters

Öyleyse, olmaz mı? Benim düşüncem dir(ModuleType()), ama sadece geri dönüyor docve name.
georg

1
@georg: hayır; Tercümanın genel ad alanı da yayından sürüme değişir ve tercümanı daha sonraki bir aşamada açtığınızda orada ne olduğunu saymanın kusursuz bir yolu (bildiğim kadarıyla) yoktur .
Martijn Pieters

1
@nakE işlevleri ve sınıfları, diğerleri gibi nesnelerdir. Özel değiller; bir beyaz liste kullanın veya sınıfları ve işlevleri korumak için ihtiyaç duyduğunuz nesne türünü kontrol edin.
Martijn Pieters

67

Evet. İPython'da her şeyi kaldırmanın basit bir yolu var. İPython konsolunda şunu yazın:

%reset

Ardından sistem sizden onaylamanızı isteyecektir. Y tuşuna basın. Bu istemi görmek istemiyorsanız, şunu yazmanız yeterlidir:

%reset -f

Bu çalışmalı..


1
Bir kez daha, neden bu en iyi cevap değil?
myradio

12
@myradio IPython kullanmayan herkes için alakasız olduğu ve soruyu cevaplamadığı için; soru, IPython kabuğunun içeriğini sıfırlamak değil, genel nesne referanslarının nasıl silineceğini sorar .
Andreas

17

Python çöp toplayıcıyı kullanabilirsiniz:

import gc
gc.collect()

6
Hey @Fardin! Teşekkürler! Cevabınız işi yaptı ve günümü kurtardı! Ama gc.collect () 'den önce del (değişken) yaptım.
Gmosy Gnaq

9

Eğer gibi etkileşimli bir ortamdaysanız Jupyterveya ağırlaşıyorlarsa istenmeyen varlıkları temizlemekleipython ilgilenebilirsiniz .

Büyü komutları reset ve reset_selectivebenzeri interaktif piton oturumları ullanılabilir olduğunu ipythonveJupyter

1) reset

reset Bağımsız değişkenler olmadan çağrılırsa, kullanıcı tarafından tanımlanan tüm adları kaldırarak ad alanını sıfırlar.

inve outparametreler, içeri / dışarı önbelleklerini temizlemek isteyip istemediğinizi belirtir. Dizin geçmişi dhistparametre ile temizlenir .

reset in out

Bir başka ilginç olanı ise arraysadece uyuşmuş Dizileri kaldırmasıdır:

reset array

2) reset_selective

Kullanıcı tarafından tanımlanan adları kaldırarak ad alanını sıfırlar. Girdi / Çıktı geçmişi, ihtiyacınız olması durumunda bırakılır.

Clean Array Örneği:

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']

Kaynak: http://ipython.readthedocs.io/en/stable/interactive/magics.html


6

Bu benim için çalıştı.

Küreseller ve ardından yereller için bir kez iki kez çalıştırmanız gerekir

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

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

4

Aslında python artık kullanılmayan belleği geri kazanacaktır. Buna python'da otomatik işlem olan çöp toplama denir . Ama yine de yapmak istiyorsanız, o zaman silebilirsiniz del variable_name. Değişkeni şuna atayarak da yapabilirsiniz.None

a = 10
print a 

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

Referans gösterilmeyen Python nesnelerinden belleği gerçekten geri kazanmanın tek yolu çöp toplayıcıdır. Del anahtar sözcüğü basitçe bir nesneden bir adın bağlantısını çözer, ancak nesnenin yine de çöp toplanması gerekir. Çöp toplayıcıyı gc modülünü kullanarak çalıştırmaya zorlayabilirsiniz, ancak bu neredeyse kesinlikle erken bir optimizasyondur, ancak kendi riskleri vardır. Kullanmanın delgerçek bir etkisi yoktur, çünkü bu isimler zaten kapsam dışına çıktıklarında silinmiş olacaktır.


Aslında. Elbette, yorumlayıcının genel ad alanında çalışırken, isimler kapsam dışına çıkmayacak, ama ne olmuş. :) Ben çöp gerçeklenime bağlıdır toplanmıştır nesneler tarafından kullanılan bellek olur, ancak çoğu Python uygulamaları içinde gc'ed bellek sadece Python havuzuna geri gider, bu oluyor olması da bahsetmemiz olduğunu tahmin değil döndü Program çıkana kadar işletim sistemi.
PM 2Ring

@ PM2Ring LOL :) Öyle düşünüyorum. Python'u nereden kastediyorsunuz?
d-coder

2
CPython'da GC'nin yalnızca referans döngülerini kırmak için gerekli olduğunu unutmayın. Herhangi bir başvuru kalması durumunda, bir amacı olan bellekten Insta-uzaklaştırıldı. Yani del yok burada gerçek bir etkiye sahiptir.
Martijn Pieters

@MartijnPieters, insta kaldırıldı mı? Bu teknik bir terim mi? :)
Eryk Paz

2
@eryksun: evet, RFC 4042-bis2 tarafından tanımlandığı gibi, tabii ki! :-P
Martijn Pieters
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.