Apakah ada cara untuk menghapus variabel, fungsi, dll yang dibuat dari memori interpreter?

114

Saya telah mencari jawaban akurat untuk pertanyaan ini selama beberapa hari sekarang tetapi belum mendapatkan hasil yang baik. Saya bukan seorang pemula yang lengkap dalam pemrograman, tetapi bahkan belum berada di tingkat menengah.

Ketika saya berada di shell Python, saya mengetik: dir()dan saya dapat melihat semua nama dari semua objek dalam lingkup saat ini (blok utama), ada 6 di antaranya:

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

Kemudian, ketika saya mendeklarasikan sebuah variabel, misalnya x = 10, itu secara otomatis menambahkan ke daftar objek di bawah modul bawaan dir(), dan ketika saya mengetik dir()lagi, itu menunjukkan sekarang:

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

Hal yang sama berlaku untuk fungsi, kelas, dan sebagainya.

Bagaimana cara menghapus semua objek baru tanpa menghapus standar 6 yang tersedia di awal?

Saya telah membaca di sini tentang "pembersihan memori", "pembersihan konsol", yang menghapus semua teks dari jendela prompt perintah:

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

Tapi semua ini tidak ada hubungannya dengan apa yang saya coba capai, itu tidak membersihkan semua objek yang digunakan.

funghorn
sumber
2
Mengapa Anda merasa perlu melakukan ini, atau Anda hanya bertanya karena ingin tahu?
PM 2Ring
Saya hanya tidak tahu bahwa ada delfungsi di luar sana. Saya mulai belajar Python dan sering harus bereksperimen di shell, jadi nama variabel standar seperti xatau ysering digunakan dan memulai ulang shell membutuhkan waktu 15 detik lagi untuk melakukannya (saya memiliki laptop yang sangat, sangat tua sekarang). Jadi saya ingin menemukan cara untuk membersihkan memori Python lebih cepat.
funghorn
1
Ah. FWIW, delsebenarnya bukan fungsi, karenanya tidak (dan ). Ini adalah kata kunci yang memperkenalkan pernyataan del. Tentu saja, cara menghapus suatu objek mungkin melibatkan fungsi, tapi itu cerita lain ...
PM 2Ring
Saat bereksperimen di nama shell seperti xatau ytidak boleh digunakan kecuali Anda menggunakannya. Atau kecuali Anda melakukan sesuatu yang konyol from _somemodule_ import *, maka Anda akan mendapatkan segala macam sampah yang mengacaukan tempat itu. :)
PM 2Ring
1
Saya mencari jalan ke pertanyaan ini di Google dan sekarang saya bertanya-tanya - mengapa saya tidak bisa memulai ulang kernel dan menjalankan kembali skrip dari atas jika saya ingin menghapus semua variabel dan fungsi?
gelandangan

Jawaban:

159

Anda dapat menghapus nama individu dengan del:

del x

atau Anda dapat menghapusnya dari globals()objek:

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

Ini hanyalah sebuah contoh loop; itu defensif hanya menghapus nama yang tidak dimulai dengan garis bawah, membuat asumsi (bukan tidak beralasan) bahwa Anda hanya menggunakan nama tanpa garis bawah di awal interpreter Anda. Anda dapat menggunakan daftar nama yang di-hardcode untuk disimpan sebagai gantinya (daftar putih) jika Anda benar-benar ingin teliti. Tidak ada fungsi bawaan untuk melakukan kliring untuk Anda, selain hanya keluar dan memulai ulang penerjemah.

Modul yang Anda impor ( import os) akan tetap diimpor karena dirujuk oleh sys.modules; impor selanjutnya akan menggunakan kembali objek modul yang sudah diimpor. Anda tidak akan memiliki referensi ke mereka di namespace global Anda saat ini.

Martijn Pieters
sumber
Yah, saya harus mengatakan startswith('_')tampaknya cukup naif. Jika seseorang cukup pintar untuk menulis _foo=42atau bahkan __foo__=42, bagaimana kita bisa menghapusnya? Apakah ada cara untuk mendapatkan nama properti modul standar secara terprogram?
georg
2
@georg: Saya telah membuat kode loop secara defensif. Anda harus membuat hardcode daftar nama awal untuk disimpan jika Anda ingin melakukannya lebih baik.
Martijn Pieters
Jadi tidak mungkin? Pikiranku dulu dir(ModuleType()), tapi itu hanya kembali docdan name.
georg
1
@georg: tidak; namespace global interpreter bervariasi dari satu rilis ke rilis lainnya, dan tidak ada cara yang sangat mudah (yang saya ketahui) untuk menyebutkan apa yang ada di sana ketika Anda membuka interpreter pada tahap selanjutnya .
Martijn Pieters
1
Fungsi dan kelas @nakE hanyalah objek seperti yang lainnya. Mereka tidak istimewa; gunakan daftar putih atau periksa jenis objek yang Anda perlukan untuk mempertahankan kelas dan fungsi.
Martijn Pieters
67

Iya. Ada cara sederhana untuk menghapus semua yang ada di iPython. Di konsol iPython, cukup ketik:

%reset

Kemudian sistem akan meminta Anda untuk mengonfirmasi. Tekan y. Jika Anda tidak ingin melihat prompt ini, cukup ketik:

%reset -f

Ini harus bekerja ..

EyesBear
sumber
1
Sekali lagi, mengapa ini bukan jawaban teratas?
myradio
11
@myradio Karena tidak relevan untuk semua orang yang tidak menggunakan IPython , dan juga tidak menjawab pertanyaan; pertanyaannya menanyakan bagaimana menghapus referensi objek global, bukan mengatur ulang konten shell IPython .
Andreas
17

Anda dapat menggunakan pengumpul sampah python:

import gc
gc.collect()
Fardin
sumber
6
Hai @Fardin! Terima kasih! Jawaban Anda berhasil dan menyelamatkan hari saya! Tetapi sebelum gc.collect () saya melakukan del (variabel).
Gmosy Gnaq
9

Jika Anda berada di lingkungan interaktif seperti Jupyteratau ipythonAnda mungkin tertarik untuk menghapus var yang tidak diinginkan jika semakin berat.

Perintah ajaib reset dan tersedia reset_selectivepada sesi python interaktif seperti ipythondanJupyter

1) reset

reset Mereset namespace dengan menghapus semua nama yang ditentukan oleh pengguna, jika dipanggil tanpa argumen.

indan outparameter menentukan apakah Anda ingin membersihkan cache masuk / keluar. Sejarah direktori dibilas dengan dhistparameter.

reset in out

Yang menarik lainnya adalah arrayhanya menghapus Array numpy:

reset array

2) reset_selective

Menyetel ulang namespace dengan menghapus nama yang ditentukan oleh pengguna. Riwayat Input / Output ditinggalkan jika Anda membutuhkannya.

Contoh Clean Array:

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

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

pengguna1767754
sumber
6

Ini berhasil untuk saya.

Anda perlu menjalankannya dua kali sekali untuk global diikuti oleh penduduk setempat

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

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

Sebenarnya python akan mengambil kembali memori yang tidak digunakan lagi, ini disebut pengumpulan sampah yang merupakan proses otomatis di python. Tetapi tetap jika Anda ingin melakukannya maka Anda dapat menghapusnya dengan del variable_name. Anda juga dapat melakukannya dengan menetapkan variabel keNone

a = 10
print a 

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

Satu-satunya cara untuk benar-benar mendapatkan kembali memori dari objek Python yang tidak direferensikan adalah melalui pengumpul sampah. Kata kunci del hanya melepaskan nama dari suatu objek, tetapi objek tersebut masih perlu dikumpulkan sampahnya. Anda dapat memaksa pengumpul sampah untuk dijalankan menggunakan modul gc, tetapi ini hampir pasti merupakan pengoptimalan yang prematur tetapi memiliki risikonya sendiri. Menggunakan deltidak memiliki efek nyata, karena nama-nama itu akan dihapus saat keluar dari ruang lingkup.

d-coder
sumber
Memang. Tentu saja, ketika bekerja di nama ruang nama global penerjemah tidak akan keluar dari ruang lingkup, tapi terus kenapa. :) Saya rasa perlu juga disebutkan bahwa apa yang terjadi pada memori yang digunakan oleh objek yang telah dikumpulkan sampahnya bergantung pada implementasi, tetapi dalam kebanyakan implementasi Python, memori gc'ed hanya kembali ke kolam Python, itu tidak dikembalikan ke OS hingga program keluar.
PM 2Ring
@ PM2Ring LOL :) Saya rasa begitu. Dari mana Anda merujuk python?
d-coder
2
Perhatikan bahwa di CPython, GC hanya diperlukan untuk memutus siklus referensi. Jika tidak ada referensi yang tersisa, sebuah objek akan dihapus secara instan dari memori. Begitu del pula memiliki efek nyata di sini.
Martijn Pieters
@MartijnPieters, dihapus insta? Apakah itu istilah teknis? :)
Eryk Sun
2
@eryksun: ya, seperti yang didefinisikan oleh RFC 4042-bis2, tentu saja! :-P
Martijn Pieters