Bagaimana cara memuat ulang modul di shell django?

90

Saya bekerja dengan Django dan menggunakan Django shell sepanjang waktu. Bagian yang mengganggu adalah sementara server Django memuat ulang pada perubahan kode, shell tidak, jadi setiap kali saya membuat perubahan ke metode yang saya uji, saya perlu keluar dari shell dan memulai ulang, mengimpor ulang semua modul yang saya perlu, menginisialisasi ulang semua variabel yang saya butuhkan, dll. Meskipun riwayat iPython menghemat banyak pengetikan, ini masih menyebalkan. Apakah ada cara untuk membuat django shell auto-reload, seperti yang dilakukan oleh server pengembangan django?

Saya tahu tentang reload (), tetapi saya mengimpor banyak model dan umumnya menggunakan from app.models import *sintaks, jadi reload () tidak banyak membantu.

Mad Wombat
sumber
2
Anda harus memperbarui pertanyaan ini untuk menandai jawaban "django-extensions" dengan benar.
woodardj
1
Tidak sampai itu benar-benar berhasil untuk saya. Saya memiliki ekstensi yang terpasang dan tidak ada kode saya yang dimuat ulang secara otomatis dan saya tidak melihat adanya pemuatan ulang otomatis di dokumen shell_plus. Sepertinya ada reloader di perintah runserver_plus, tapi bukan itu yang saya cari.
Mad Wombat

Jawaban:

37

Saya merekomendasikan menggunakan proyek ekstensi-django seperti yang disebutkan di atas oleh dongweiming. Tetapi alih-alih hanya perintah manajemen 'shell_plus', gunakan:

manage.py shell_plus --notebook

Ini akan membuka notebook IPython di browser web Anda. Tulis kode Anda di sana di sel, impor Anda, dll. Dan jalankan.

Ketika Anda mengubah modul Anda, cukup klik item menu notebook 'Kernel-> Restart'

Ini dia, kode Anda sekarang menggunakan modul yang telah Anda modifikasi.

mpaf
sumber
30
"Gunakan saja notebook python" bukanlah jawaban untuk pertanyaan OP.
J__
Metode ini, meskipun tidak otomatis seperti% autoreload, bekerja lebih andal daripada autoreload. restart kernel menjamin bahwa semua sel di notebook mendapatkan modul yang dimuat ulang sepenuhnya. Selain itu, Anda dapat memulai ulang dan menjalankan semua sel jika Anda mau.
Anton I. Sipos
72

Saya sarankan menggunakan ekstensi autoreload IPython .

./manage.py shell

In [1]: %load_ext autoreload
In [2]: %autoreload 2

Dan mulai sekarang semua modul yang diimpor akan disegarkan sebelum dievaluasi.

In [3]: from x import print_something
In [4]: print_something()
Out[4]: 'Something'

 # Do changes in print_something method in x.py file.

In [5]: print_something()
Out[5]: 'Something else'

Bekerja juga jika ada sesuatu yang diimpor sebelum %load_ext autoreloadperintah.

./manage.py shell
In [1]: from x import print_something
In [2]: print_something()
Out[2]: 'Something'

 # Do changes in print_something method in x.py file.

In [3]: %load_ext autoreload
In [4]: %autoreload 2
In [5]: print_something()
Out[5]: 'Something else'

Ada juga kemungkinan mencegah beberapa impor dari %aimportrefresh dengan perintah dan 3 strategi autoreload:

% autoreload

  • Muat ulang semua modul (kecuali yang dikecualikan oleh% aimport) secara otomatis sekarang.

% autoreload 0

  • Nonaktifkan pemuatan ulang otomatis.

% autoreload 1

  • Muat ulang semua modul yang diimpor dengan% aimport setiap kali sebelum menjalankan kode Python yang diketik.

% autoreload 2

  • Muat ulang semua modul (kecuali yang dikecualikan oleh% aimport) setiap kali sebelum menjalankan kode Python yang diketik.

% aimport

  • Daftar modul yang akan diimpor secara otomatis atau tidak untuk diimpor.

% aimport foo

  • Impor modul 'foo' dan tandai sebagai dimuat otomatis untuk% autoreload 1

% aimport -foo

  • Tandai modul 'foo' untuk tidak dimuat otomatis.

Ini biasanya berfungsi baik untuk saya gunakan, tetapi ada beberapa cavetas:

  • Mengganti objek kode tidak selalu berhasil: mengubah @property di kelas menjadi metode biasa atau metode ke variabel anggota dapat menyebabkan masalah (tetapi hanya di objek lama).
  • Fungsi yang dihapus (mis. Melalui monkey-patching) dari modul sebelum dimuat ulang tidak akan ditingkatkan.
  • Modul ekstensi C tidak dapat dimuat ulang, sehingga tidak dapat dimuat secara otomatis.
bodolsog
sumber
3
Jika Anda menggunakan django /manage.py shell_plus... jika Anda mengetik %load_ext autoreloaddan kemudian %autoreload 2, model akan dimuat ulang secara otomatis.
Fusion
Luar biasa, Anda membuat hari saya menyenangkan
Shamsul Arefin Sajib
Perhatikan bahwa Anda membutuhkan ipython untuk diinstal untuk ini, jelas. Lihat misalnya stackoverflow.com/a/47170195/50899
Rabarberski
38

lihat perintah manage.py shell_plus yang disediakan oleh proyek django-extensions . Ini akan memuat semua file model Anda pada startup shell. dan autoreload apapun yang anda modifikasi tapi tidak perlu keluar, anda bisa langsung menelpon kesana

dongweiming
sumber
40
Saya menggunakan shell_plus dan model saya tidak memuat ulang otomatis, apakah saya melewatkan sesuatu?
Diego Ponciano
30
shell_plus tidak memuat ulang model, jadi ini tidak menjawab pertanyaan.
aljabear
5
seperti yang dikatakan, shell_plus tidak memuat ulang model.
zenperttu
2
Mungkin saya melewatkan sesuatu, tetapi shell_plus tidak memuat ulang apa pun untuk saya. Itu memuat semua model saat startup, yang nyaman, tetapi hanya itu.
Mad Wombat
14
shell_plus DAPAT memuat ulang modul menggunakan modul autoreload. Ketik '% load_ext autoreload' dan kemudian '% autoreload 2' - lihat ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame
37

Solusi saya untuk itu adalah saya menulis kode dan menyimpan ke file dan kemudian menggunakan:

python manage.py shell <test.py

Jadi saya bisa melakukan perubahan, menyimpan dan menjalankan perintah itu lagi sampai saya memperbaiki apa pun yang saya coba perbaiki.

Erik
sumber
2
Bagus dan sederhana. Satu catatan, tambahkan exit()ke bagian bawah file py untuk keluar dari shell Django dengan cara yang lebih bersih. Terima kasih.
Marc
Solusi sederhana dan elegan. Kerja bagus.
nikoskip
25

Tampaknya konsensus umum tentang topik ini, adalah bahwa python reload () menyebalkan dan tidak ada cara yang baik untuk melakukan ini.

Mad Wombat
sumber
Salah. Jawaban @ dongweiming di atas adalah solusinya, dan harus diterima sebagai jawaban terbaik.
Joseph Sheedy
3
Beberapa komentar pada jawabannya mengatakan bahwa shell_plus tidak memuat ulang model
Mad Wombat
1
Saya baru saja mengujinya sendiri dan tidak dimuat ulang. Selain itu, bagaimana dengan kode non-model yang saya impor secara manual?
Mad Wombat
Kelas-kelas dalam aplikasi yang saya gunakan sekarang muat ulang (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), termasuk modul model non-django dan kelas di dalamnya. Sudah 5 tahun sejak jawaban ini, dan banyak perkembangan telah terjadi.
Joseph Sheedy
1
Saya telah mencobanya di pengaturan saya 40 menit yang lalu dan shell_plus tidak memuat ulang apa pun untuk saya. Django 1.7.10, python 3.4.3, django-extensions 1.5.9.
Mad Wombat
5

Solusi saya untuk ketidaknyamanan ini berikut. Saya menggunakan IPython.

$ ./manage.py shell
> import myapp.models as mdls   # 'mdls' or whatever you want, but short...
> mdls.SomeModel.objects.get(pk=100)
> # At this point save some changes in the model
> reload(mdls)
> mdls.SomeModel.objects.get(pk=100)

Untuk Python 3.x , 'reload' harus diimpor menggunakan:

from importlib import reload

Semoga membantu. Tentu saja ini untuk tujuan debug.

Bersulang.

Roque
sumber
2

Gunakan shell_plus dengan konfigurasi ipython. Ini akan memungkinkan autoreloadsebelum shell_plus mengimpor apapun secara otomatis.

pip install django-extensions
pip install ipython
ipython profile create

Edit profil ipython Anda ( ~/.ipython/profile_default/ipython_config.py):

c.InteractiveShellApp.exec_lines = ['%autoreload 2']
c.InteractiveShellApp.extensions = ['autoreload']

Buka shell - perhatikan bahwa Anda tidak perlu menyertakan --ipython:

python manage.py shell_plus

Sekarang apapun yang didefinisikan di SHELL_PLUS_PRE_IMPORTSatau SHELL_PLUS_POST_IMPORTS( docs ) akan dimuat secara otomatis!

Perhatikan bahwa jika shell Anda berada di debugger (ex pdb.set_trace()) saat Anda menyimpan file, hal itu dapat mengganggu pemuatan ulang.

andorov
sumber
1
Terima kasih atas jawabannya. Anda mungkin memperhatikan, bahwa saya menanyakannya pada tahun 2010. Saya senang mengetahui bahwa setelah delapan tahun muat ulang otomatis akhirnya berfungsi di shell_plus :)
Mad Wombat
1

Alih-alih menjalankan perintah dari shell Django, Anda dapat menyetel perintah manajemen seperti itu dan menjalankannya kembali setiap saat.

Littlegreen
sumber
0

Tidak persis seperti yang Anda inginkan, tetapi sekarang saya cenderung membuat sendiri perintah manajemen untuk menguji dan mengotak-atik berbagai hal.

Dalam perintah, Anda dapat mengatur sekelompok penduduk setempat seperti yang Anda inginkan dan kemudian masuk ke shell interaktif.

import code

class Command(BaseCommand):
  def handle(self, *args, **kwargs):
     foo = 'bar'
     code.interact(local=locals())

Tanpa memuat ulang, tetapi cara yang mudah dan tidak terlalu mengganggu untuk menguji fungsionalitas django secara interaktif.

toabi
sumber