Masukkan kembali modul dengan python sambil interaktif

384

Saya tahu itu bisa dilakukan, tetapi saya tidak pernah ingat caranya.

Bagaimana Anda dapat mengimpor kembali modul dengan python? Skenarionya adalah sebagai berikut: Saya mengimpor modul secara interaktif dan mengotak-atiknya, tetapi kemudian saya menghadapi kesalahan. Saya memperbaiki kesalahan dalam file .py dan kemudian saya ingin mengembalikan modul tetap tanpa berhenti python. Bagaimana saya bisa melakukannya?

Stefano Borini
sumber

Jawaban:

370

Ini seharusnya bekerja:

reload(my.module)

Dari dokumen Python

Muat ulang modul yang sebelumnya diimpor. Argumen harus berupa objek modul, sehingga harus sudah berhasil diimpor sebelumnya. Ini berguna jika Anda telah mengedit file sumber modul menggunakan editor eksternal dan ingin mencoba versi baru tanpa meninggalkan juru bahasa Python.

Jika menjalankan Python 3.4 ke atas, lakukan import importlib, lalu lakukan importlib.reload(nameOfModule).

Jangan lupa peringatan menggunakan metode ini:

  • Ketika modul dimuat ulang, kamusnya (berisi variabel global modul) dipertahankan. Redefinisi nama akan menimpa definisi lama, jadi ini umumnya tidak menjadi masalah, tetapi jika versi baru modul tidak mendefinisikan nama yang ditentukan oleh versi lama, definisi lama tidak dihapus.

  • Jika modul mengimpor objek dari modul lain menggunakan from ... import ..., memanggil reload()modul lain tidak mendefinisikan ulang objek yang diimpor darinya - salah satu cara untuk menyelesaikan ini adalah mengeksekusi ulang frompernyataan, yang lain adalah dengan menggunakan importdan nama yang memenuhi syarat ( module.*name*) sebagai gantinya.

  • Jika modul instantiates instance kelas, memuat ulang modul yang mendefinisikan kelas tidak mempengaruhi definisi metode dari instance - mereka terus menggunakan definisi kelas yang lama. Hal yang sama berlaku untuk kelas turunan.

Benjamin Wohlwend
sumber
26
jika saya memuat modul saya menggunakan from filename import *. Bagaimana cara memuat ulang?
Peter Zhu
@ PeterZhu untuk kasus "dari mod import fcn", objek modul tidak ditambahkan ke ruang nama. Jadi, Anda perlu mengimpor modul secara eksplisit, sehingga nanti Anda dapat memuatnya kembali. import foo; from foo import bar; reload(foo)
Ted
Saya mencoba memuat ulang, serta sihir autoreload, dan saya melihat perubahan kode saya tercermin dalam tumpukan pesan kesalahan, tetapi kesalahan itu sendiri tampaknya masih dari kode basi (misalnya, garis kesalahan adalah pada saat yang sama persis baris seperti sebelumnya, yang telah saya ubah menjadi komentar, dan komentar jelas tidak dapat menyebabkan kesalahan). Modul saya dimuat sebagai Ekstensi Jupyter, mungkin ada yang tahu jika ini membutuhkan pekerjaan yang berbeda? Terima kasih!
yifanwu
1
Jika Anda mengimpor fungsi Anda sebagai berikut "import mod as name", maka Anda perlu melakukan hal berikut: 'import importlib importlib.reload (name)'
Noe
Metode ini mungkin tidak menimpa referensi modul lain ke modul yang dimuat ulang. Lihat stackoverflow.com/a/61617169/2642356 untuk solusinya.
EZLearner
288

Dalam python 3, reloadtidak ada lagi fungsi bawaan.

Jika Anda menggunakan python 3.4+ Anda harus menggunakan reloaddari importlibperpustakaan sebagai gantinya:

import importlib
importlib.reload(some_module)

Jika Anda menggunakan python 3.2 atau 3.3, Anda harus:

import imp  
imp.reload(module)  

sebagai gantinya. Lihat http://docs.python.org/3.0/library/imp.html#imp.reload

Jika Anda menggunakan ipython, pasti pertimbangkan untuk menggunakan autoreloadekstensi:

%load_ext autoreload
%autoreload 2
Andrew
sumber
Meskipun banyak kode Python ditulis dalam Python 2, Python 3 menjadi opsi yang lebih layak setiap hari. Terima kasih atas tipnya!
Aaron Johnson
40
imp.reloadsudah ditinggalkan sejak Python 3.4, gunakan importlib.reloadfungsi sebagai gantinya.
jfs
1
@Andrew terima kasih! Saya menggunakan% autoreload, luar biasa, objek-objek saya yang sudah dibuat mendapat implementasi metode kelas yang diperbaiki tanpa harus membuatnya kembali
jeanmi
4
Saya sedikit terlambat, tapi saya pikir ini tidak bekerja jika apa yang Anda butuhkan untuk isi ulang adalah fungsi atau kelas dari dalam modul: jika pernyataan impor saya from mymodule import myfunc, maka importlib.reload(myfunc), importlib.reload(mymodule.myfunc), importlib.reload(mymodule)semua memberikan NameError.
Puff
@Puff lihat jawaban saya di bawah ini untuk cara mengimpor kembali fungsi
jss367
46

Sebenarnya, dalam Python 3 modul impditandai sebagai TERDEPAN. Ya, setidaknya itu berlaku untuk 3.4.

Sebaliknya reloadfungsi dari importlibmodul harus digunakan:

https://docs.python.org/3/library/importlib.html#importlib.reload

Namun ketahuilah bahwa perpustakaan ini memiliki beberapa perubahan API dengan dua versi minor terakhir.

masa depan yang funky
sumber
6

Jika Anda ingin mengimpor fungsi atau kelas tertentu dari modul, Anda dapat melakukan ini:

import importlib
import sys
importlib.reload(sys.modules['my_module'])
from my_module import my_function
jss367
sumber
0

Meskipun jawaban yang diberikan berfungsi untuk modul tertentu, mereka tidak akan memuat ulang submodul, seperti yang tercantum dalam jawaban ini :

Jika modul mengimpor objek dari modul lain menggunakan from ... import ..., memanggil reload()modul lain tidak mendefinisikan ulang objek yang diimpor darinya - salah satu cara untuk menyelesaikan ini adalah mengeksekusi ulang dari pernyataan, yang lain adalah menggunakan importdan nama yang memenuhi syarat ( module.*name*) sebagai gantinya.

Namun, jika menggunakan __all__variabel untuk mendefinisikan API publik, dimungkinkan untuk memuat ulang semua modul yang tersedia secara publik:

# Python >= 3.5
import importlib
import types


def walk_reload(module: types.ModuleType) -> None:
    if hasattr(module, "__all__"):
        for submodule_name in module.__all__:
            walk_reload(getattr(module, submodule_name))
    importlib.reload(module)


walk_reload(my_module)

Peringatan yang tercantum dalam jawaban sebelumnya masih valid. Khususnya, memodifikasi submodule yang bukan bagian dari API publik seperti yang dijelaskan oleh __all__variabel tidak akan terpengaruh oleh reload menggunakan fungsi ini. Demikian pula, menghapus elemen submodule tidak akan tercermin dengan memuat ulang.

skasch
sumber