Saya memiliki server Python yang sudah berjalan lama dan ingin dapat meningkatkan layanan tanpa me-restart server. Apa cara terbaik melakukan ini?
if foo.py has changed:
unimport foo <-- How do I do this?
import foo
myfoo = foo.Foo()
python
module
reload
python-import
Mark Harrison
sumber
sumber
Jawaban:
Anda dapat memuat ulang modul ketika sudah diimpor dengan menggunakan
reload
fungsi builtin (hanya Python 3.4+) :Dalam Python 3,
reload
dipindahkan keimp
modul. Dalam 3.4,imp
tidak digunakan lagiimportlib
, danreload
ditambahkan ke yang terakhir. Saat menargetkan 3 atau lebih baru, rujuk modul yang sesuai saat memanggilreload
atau mengimpornya.Saya pikir inilah yang Anda inginkan. Server web seperti server pengembangan Django menggunakan ini sehingga Anda dapat melihat efek dari perubahan kode Anda tanpa memulai ulang proses server itu sendiri.
Mengutip dari dokumen:
Seperti yang Anda catat dalam pertanyaan Anda, Anda harus merekonstruksi
Foo
objek jikaFoo
kelas berada difoo
modul.sumber
X
bukan modul, Anda bisaimport sys; reload(sys.modules[X.__module__])
is_changed
fungsi ini hanyalah fungsi arbitrer yang harus Anda tulis; ini bukan built-in. Sebagai contoh, itu bisa membuka file yang sesuai dengan modul yang Anda impor dan memperbaikinya dengan versi cache untuk melihat apakah itu berubah.Dalam Python 3.0–3.3 Anda akan menggunakan:
imp.reload(module)
The BDFL telah menjawab pertanyaan ini.
Namun,
imp
sudah usang dalam 3.4, mendukungimportlib
(terima kasih @Stefan! ).Saya pikir , oleh karena itu, sekarang Anda akan menggunakan
importlib.reload(module)
, meskipun saya tidak yakin.sumber
reload(__builtins__)
berlaku di 2.xIni bisa sangat sulit untuk menghapus modul jika itu bukan Python murni.
Berikut ini beberapa informasi dari: Bagaimana cara saya benar-benar menghapus modul yang diimpor?
sumber
setattr(package, "empty", None)
reload()
hanya memuat ulang modul paling atas, dan apa pun di dalamnya tidak akan dimuat ulang kecuali Anda terlebih dahulu menghapusnya dari sys.modules.reload(module)
, tetapi hanya jika itu sepenuhnya berdiri sendiri. Jika ada hal lain yang memiliki referensi ke modul (atau objek apa pun yang termasuk dalam modul), maka Anda akan mendapatkan kesalahan halus dan aneh yang disebabkan oleh kode lama yang berkeliaran lebih lama dari yang Anda harapkan, dan hal-hal sepertiisinstance
tidak bekerja di berbagai versi berbeda dari modul. kode yang sama.Jika Anda memiliki dependensi satu arah, Anda juga harus memuat ulang semua modul yang bergantung pada modul yang dimuat ulang untuk menyingkirkan semua referensi ke kode lama. Dan kemudian memuat kembali modul yang bergantung pada modul yang dimuat ulang, secara rekursif.
Jika Anda memiliki dependensi melingkar, yang sangat umum misalnya ketika Anda berurusan dengan memuat ulang paket, Anda harus membongkar semua modul dalam grup sekaligus. Anda tidak dapat melakukan ini dengan
reload()
karena itu akan mengimpor kembali setiap modul sebelum dependensinya telah di-refresh, memungkinkan referensi lama masuk ke modul-modul baru.Satu-satunya cara untuk melakukannya dalam hal ini adalah meretas
sys.modules
, yang agak tidak didukung. Anda harus melalui dan menghapus setiapsys.modules
entri yang ingin Anda muat ulang pada impor berikutnya, dan juga menghapus entri yang nilainyaNone
berurusan dengan masalah implementasi terkait dengan caching impor relatif yang gagal. Ini tidak terlalu bagus tetapi selama Anda memiliki satu set dependensi mandiri yang tidak meninggalkan referensi di luar basis kode, itu bisa diterapkan.Mungkin yang terbaik untuk me-restart server. :-)
sumber
None
nilai - nilai karena saya menjalankan persis masalah ini: Saya menghapus item darisys.modules
dan setelah mengimpor kembali beberapa dependensi yang diimporNone
.None
entri berhasil membuat jalan kembali melalui mekanisme impor ketika entri 'nyata' dihapus, dan saya tidak bisa mewujudkannya pada 2.7; di masa depan tentu itu tidak lagi menjadi masalah karena impor relatif implisit telah hilang. Sementara itu, menghapus semua entri denganNone
nilai tampaknya memperbaikinya.reload
fungsinya? Ini built-in, Anda tidak perlu mengimpor perpustakaan apa pun.sumber
nose.run()
, bahkan setelahreload(my_module)
%run my_module
[del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')]
.import sys; import json; del sys.modules['json']; print(json.dumps([1]))
dan modul json masih berfungsi meskipun tidak ada di sys.modules lagi.Untuk Python 2 gunakan fungsi reload bawaan () :
Untuk Python 2 dan 3.2-3.3 gunakan ulang dari modul imp :
Tetapi
imp
sudah ditinggalkan sejak versi 3.4 yang mendukung importlib , jadi gunakan:atau
sumber
from six import reload_module
(haruspip install six
terlebih dahulu tentu saja)from six.moves import reload_module
( doc )Kode berikut memungkinkan Anda kompatibilitas Python 2/3:
Anda dapat menggunakannya seperti
reload()
di kedua versi yang membuat semuanya lebih sederhana.sumber
Jawaban yang diterima tidak menangani kasus dari X import Y. Kode ini menanganinya dan kasing standar juga:
Dalam kasus memuat ulang, kami menetapkan kembali nama tingkat atas ke nilai yang disimpan dalam modul yang baru dimuat, yang memperbaruinya.
sumber
>>> from X import Y
memuat ulang lakukan>>> __import__('X', fromlist='Y')
fromlist='*'
?from
dalam laporan impor. Hanya paket.simbol yangimport <package>
jelas dan eksplisit dalam kode. Sadarilah ini mungkin tidak selalu mungkin atau diinginkan. (Ini satu pengecualian: dari import print_function yang akan datang.)foo = reload(foo); from foo import *
Ini adalah cara modern memuat ulang modul:
Jika Anda ingin mendukung versi Python yang lebih lama dari 3,5, coba ini:
Untuk menggunakannya, jalankan
reload(MODULE)
, gantiMODULE
dengan modul yang ingin Anda muat ulang.Misalnya,
reload(math)
akan memuat ulangmath
modul.sumber
from importlib import reload
. Maka Anda bisa melakukannyareload(MODULE_NAME)
. Tidak perlu untuk fungsi ini.modulereload(MODULE_NAME)
lebih jelas dari pada adilreload(MODULE_NAME)
dan memiliki peluang lebih rendah untuk konflik dengan fungsi lain.Jika Anda tidak berada di server, tetapi sedang mengembangkan dan perlu sering memuat ulang modul, inilah tip yang bagus.
Pertama, pastikan Anda menggunakan shell IPython yang luar biasa , dari proyek Notebook Jupyter. Setelah menginstal Jupyter, Anda dapat memulainya dengan
ipython
, ataujupyter console
, atau bahkan lebih baikjupyter qtconsole
,, yang akan memberi Anda konsol berwarna yang bagus dengan penyelesaian kode di OS apa pun.Sekarang di shell Anda, ketik:
Sekarang, setiap kali Anda menjalankan skrip, modul Anda akan dimuat ulang.
Di luar itu
2
, ada opsi lain dari autoreload magic :sumber
Bagi mereka seperti saya yang ingin membongkar semua modul (saat menjalankan interpreter Python di bawah Emacs ):
Informasi lebih lanjut ada di Reload modul Python .
sumber
sys.modules.values()
ada dalam modul. Sebagai contoh: >>> ketik (sys.modules.values () [1]) <class 'email.LazyImporter'> Jadi, jika saya mencoba menjalankan kode yang terjatuh (Saya Tahu itu tidak dimaksudkan sebagai solusi praktis, cukup menunjukkan itu).if mod and mod.__name__ != "__main__": imp.reload(mod)
Ciri-ciri Enthought memiliki modul yang bekerja cukup baik untuk ini. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
Ini akan memuat kembali modul apa pun yang telah diubah, dan memperbarui modul lain dan objek yang digunakan yang menggunakannya. Itu tidak bekerja sebagian besar waktu dengan
__very_private__
metode, dan dapat tersedak warisan kelas, tapi itu menghemat waktu yang gila karena harus me-restart aplikasi host ketika menulis PyQt guis, atau hal-hal yang berjalan di dalam program seperti Maya atau Nuke. Itu tidak berhasil mungkin 20-30% dari waktu, tetapi masih sangat membantu.Paket Enthought tidak memuat ulang file saat mereka berubah - Anda harus menyebutnya secara eksplisit - tetapi itu seharusnya tidak terlalu sulit untuk diterapkan jika Anda benar-benar membutuhkannya
sumber
Mereka yang menggunakan python 3 dan memuat ulang dari importlib.
Jika Anda memiliki masalah seperti itu tampaknya modul tidak memuat ulang ... Itu karena perlu beberapa waktu untuk mengkompilasi ulang pyc (hingga 60 detik). Saya menulis petunjuk ini hanya agar Anda tahu jika Anda pernah mengalami masalah seperti ini.
sumber
2018-02-01
foo
harus berhasil diimpor terlebih dahulu.from importlib import reload
,reload(foo)
31.5. importlib - Implementasi impor - dokumentasi Python 3.6.4
sumber
Pilihan lain. Lihat bahwa standar Python
importlib.reload
hanya akan mengimpor kembali pustaka yang diteruskan sebagai argumen. Itu tidak akan memuat ulang perpustakaan yang diimpor lib Anda. Jika Anda mengubah banyak file dan memiliki paket yang agak rumit untuk diimpor, Anda harus melakukan pemuatan ulang yang dalam .Jika Anda menginstal IPython atau Jupyter , Anda dapat menggunakan fungsi untuk memuat ulang semua lib secara mendalam:
Jika Anda tidak memiliki Jupyter, instal dengan perintah ini di shell Anda:
sumber
reload() argument must be module
. Saya menggunakan impor fungsi khusus dan sepertinya tidak berfungsi. Menggunakan modul bawaan tidak berfungsi. :-( itu buang-buang waktu me-reload iPython untuk setiap perubahan kecil yang saya lakukan pada kode saya ...Edit (Jawab V2)
Solusi dari sebelumnya baik untuk hanya mendapatkan informasi reset, tetapi tidak akan mengubah semua referensi (lebih dari
reload
tetapi kurang dari yang dibutuhkan). Untuk benar-benar mengatur semua referensi juga, saya harus pergi ke pengumpul sampah, dan menulis ulang referensi di sana. Sekarang ini berfungsi seperti pesona!Perhatikan bahwa ini tidak akan berfungsi jika GC dimatikan, atau jika memuat ulang data yang tidak dipantau oleh GC. Jika Anda tidak ingin mengacaukan dengan GC, jawaban asli mungkin cukup untuk Anda.
Kode baru:
Jawaban Asli
Seperti yang ditulis dalam jawaban @ bobince, jika sudah ada referensi ke modul itu di modul lain (terutama jika itu diimpor dengan
as
kata kunci sepertiimport numpy as np
), contoh itu tidak akan ditimpa.Hal ini terbukti cukup bermasalah dengan saya ketika menerapkan tes yang diperlukan "bersih-batu tulis" keadaan modul konfigurasi, jadi saya telah menulis sebuah fungsi bernama
reset_module
yang menggunakanimportlib
'sreload
fungsi dan secara rekursif menimpa semua atribut modul dideklarasikan ini. Telah diuji dengan Python versi 3.6.Catatan: Gunakan dengan hati-hati! Menggunakan ini pada modul non-periferal (modul yang mendefinisikan kelas yang digunakan secara eksternal, misalnya) dapat menyebabkan masalah internal dengan Python (seperti masalah pickling / un-pickling).
sumber
bagi saya untuk kasus Abaqus itu cara kerjanya. Bayangkan file Anda adalah Class_VerticesEdges.py
sumber
Saya mendapat banyak kesulitan mencoba memuat ulang sesuatu di dalam Sublime Text, tetapi akhirnya saya dapat menulis utilitas ini untuk memuat kembali modul pada Sublime Text berdasarkan kode yang
sublime_plugin.py
digunakan untuk memuat kembali modul.Di bawah ini menerima Anda untuk memuat ulang modul dari jalur dengan spasi di namanya, kemudian setelah memuat ulang Anda dapat mengimpor seperti biasa.
Jika Anda menjalankan untuk pertama kalinya, ini akan memuat modul, tetapi jika nanti Anda dapat kembali metode / fungsinya
run_tests()
itu akan memuat kembali file tes. Dengan Sublime Text (Python 3.3.6
) ini sering terjadi karena interpreternya tidak pernah ditutup (kecuali Anda me-restart Sublime Text, yaituPython3.3
interpreter).sumber
Cara lain bisa dengan mengimpor modul dalam suatu fungsi. Dengan cara ini ketika fungsi selesai modul mendapat sampah yang dikumpulkan.
sumber
sys.modules
.