Làm thế nào để tải lại các mô-đun trong django shell?


90

Tôi đang làm việc với Django và sử dụng Django shell mọi lúc. Phần khó chịu là trong khi máy chủ Django tải lại các thay đổi mã, trình bao thì không, vì vậy mỗi khi tôi thực hiện thay đổi đối với một phương pháp tôi đang thử nghiệm, tôi cần phải thoát trình bao và khởi động lại nó, nhập lại tất cả các mô-đun của tôi. cần, khởi động lại tất cả các biến tôi cần, v.v. Trong khi lịch sử iPython tiết kiệm rất nhiều lần gõ vào điều này, đây vẫn là một nỗi đau. Có cách nào để làm cho trình bao django tự động tải lại, giống như cách máy chủ phát triển django làm không?

Tôi biết về reload (), nhưng tôi nhập rất nhiều mô hình và thường sử dụng from app.models import *cú pháp, vì vậy reload () không giúp ích được nhiều.


2
Bạn nên cập nhật câu hỏi này để đánh dấu câu trả lời "django-extensions" là đúng.
woodardj

1
Không cho đến khi nó thực sự hiệu quả với tôi. Tôi đã cài đặt các tiện ích mở rộng và không có mã nào tự động tải lại và tôi không thấy bất kỳ đề cập nào về tự động tải lại trong tài liệu shell_plus. Có vẻ như có một trình tải lại trong lệnh runningerver_plus, nhưng đó không phải là những gì tôi đang tìm kiếm.
Mad Wombat

Câu trả lời:


37

Tôi khuyên bạn nên sử dụng dự án django-extensions như đã nêu ở trên của dongweiming. Nhưng thay vì chỉ lệnh quản lý 'shell_plus', hãy sử dụng:

manage.py shell_plus --notebook

Thao tác này sẽ mở một sổ ghi chép IPython trên trình duyệt web của bạn. Viết mã của bạn ở đó trong một ô, nhập của bạn, v.v. và chạy nó.

Khi bạn thay đổi mô-đun của mình, chỉ cần nhấp vào mục menu sổ tay 'Kernel-> Restart'

Vậy là xong, mã của bạn hiện đang sử dụng các mô-đun đã sửa đổi của bạn.


30
"Chỉ sử dụng máy tính xách tay python" không phải là câu trả lời cho câu hỏi của OP.
J__

Phương pháp này, mặc dù không tự động như% autoreload, nhưng hoạt động đáng tin cậy hơn so với autoreload. khởi động lại hạt nhân đảm bảo rằng tất cả các ô trong sổ ghi chép được tải lại đầy đủ các mô-đun. Ngoài ra, bạn có thể khởi động lại và chạy tất cả các ô nếu bạn chọn.
Anton I. Sipos

72

Tôi khuyên bạn nên sử dụng tiện ích mở rộng tải tự động IPython .

./manage.py shell

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

Và từ bây giờ, tất cả các mô-đun đã nhập sẽ được làm mới trước khi đánh giá.

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'

Cũng hoạt động nếu một cái gì đó được nhập trước %load_ext autoreloadlệnh.

./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'

Cũng có thể ngăn một số nhập làm mới bằng %aimportlệnh và 3 chiến lược tải tự động:

%Nạp lại tự động

  • Tự động tải lại tất cả các mô-đun (trừ những mô-đun bị% aimport loại trừ) ngay bây giờ.

% autoreload 0

  • Tắt tải lại tự động.

% autoreload 1

  • Tải lại tất cả các mô-đun đã nhập với% aimport mọi lúc trước khi thực thi mã Python đã nhập.

% autoreload 2

  • Tải lại tất cả các mô-đun (ngoại trừ những mô-đun bị% aimport loại trừ) trước khi thực thi mã Python đã nhập.

% aimport

  • Liệt kê các mô-đun sẽ được nhập tự động hoặc không được nhập.

% aimport foo

  • Nhập mô-đun 'foo' và đánh dấu nó sẽ được tải tự động cho% autoreload 1

% aimport -foo

  • Đánh dấu mô-đun 'foo' để không được tải lại tự động.

Điều này thường hoạt động tốt cho việc sử dụng của tôi, nhưng có một số điều cần lưu ý:

  • Việc thay thế các đối tượng mã không phải lúc nào cũng thành công: việc thay đổi @property trong một lớp thành một phương thức thông thường hoặc một phương thức thành một biến thành viên có thể gây ra vấn đề (nhưng chỉ trong các đối tượng cũ).
  • Các chức năng bị xóa (ví dụ: thông qua khỉ vá) khỏi một mô-đun trước khi tải lại sẽ không được nâng cấp.
  • Không thể tải lại các mô-đun mở rộng C và do đó không thể tự động tải lại.

3
Trong trường hợp bạn đang sử dụng django's /manage.py shell_plus... nếu bạn nhập %load_ext autoreloadvà sau đó %autoreload 2, các mô hình sẽ tự động được tải lại.
Fusion

Tuyệt vời, bạn đã thực hiện trong ngày của tôi
Shamsul Arefin Sajib

Lưu ý rằng bạn cần phải cài đặt ipython cho việc này. Xem ví dụ: stackoverflow.com/a/47170195/50899
Rabarberski

38

nhìn vào lệnh management.py shell_plus do dự án django-extensions cung cấp . Nó sẽ tải tất cả các tệp mô hình của bạn khi khởi động shell. và tự động tải lại bất kỳ sửa đổi nào của bạn nhưng không cần thoát, bạn có thể gọi trực tiếp ở đó


40
Tôi sử dụng shell_plus và các mô hình của tôi không tự động tải lại, tôi có thiếu thứ gì không?
Diego Ponciano

30
shell_plus không tải lại các mô hình, vì vậy điều này không trả lời câu hỏi.
aljabear

5
như đã nói, shell_plus không tải lại các mô hình.
zenperttu

2
Có thể tôi đang thiếu một cái gì đó, nhưng shell_plus không tải lại bất kỳ thứ gì cho tôi. Nó tải tất cả các mô hình khi khởi động, điều này thật tiện lợi, nhưng chỉ có vậy.
Mad Wombat

14
shell_plus CÓ THỂ tải lại các mô-đun bằng cách sử dụng mô-đun tải tự động. Gõ '% load_ext tự động nạp lại' và sau đó '% tự động nạp lại 2' - xem ipython.org/ipython-doc/3/config/extensions/autoreload.html
bbrame

37

Giải pháp của tôi là tôi viết mã và lưu vào một tệp rồi sử dụng:

python management.py shell <test.py

Vì vậy, tôi có thể thực hiện thay đổi, lưu và chạy lại lệnh đó cho đến khi tôi sửa được bất cứ điều gì tôi đang cố gắng sửa.


2
Đẹp và đơn giản. Một lưu ý, hãy thêm exit()vào cuối tệp py để thoát khỏi trình bao Django theo cách gọn gàng hơn. Cám ơn.
Marc

Giải pháp đơn giản và thanh lịch. Làm tốt lắm.
nikoskip

25

Có vẻ như sự đồng thuận chung về chủ đề này là python reload () rất tệ và không có cách nào tốt để làm điều này.


Sai. Câu trả lời của @ dongweiming ở trên là giải pháp và nên được chấp nhận là câu trả lời tốt nhất.
Joseph Sheedy

3
Nhiều ý kiến về nói câu trả lời của ông rằng shell_plus không tải lại mô hình
Mad Wombat

1
Tôi vừa thử nghiệm nó cho mình và nó không tải lại. Bên cạnh đó, những gì không phải mã mẫu tôi nhập bằng tay?
Mad Wombat

Các lớp trong ứng dụng tôi đang sử dụng hiện tải lại rất tốt (Python 3.4.3, Django 1.9b1, django-extensions 1.5.9), bao gồm mô-đun không phải mô hình django đơn giản và lớp bên trong nó. Đã 5 năm kể từ câu trả lời này, và rất nhiều sự phát triển đã xảy ra.
Joseph Sheedy

1
Tôi đã thử nó trên thiết lập của mình 40 phút trước và shell_plus không tải lại bất kỳ thứ gì cho tôi. Django 1.7.10, python 3.4.3, django-extension 1.5.9.
Mad Wombat


5

Giải pháp của tôi cho sự bất tiện này sau đây. Tôi đang sử dụng 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)

Đối với Python 3.x , 'tải lại' phải được nhập bằng:

from importlib import reload

Hy vọng nó giúp. Tất nhiên nó là cho mục đích gỡ lỗi.

Chúc mừng.


2

Sử dụng shell_plus với cấu hình ipython. Điều này sẽ kích hoạt autoreloadtrước khi shell_plus tự động nhập bất kỳ thứ gì.

pip install django-extensions
pip install ipython
ipython profile create

Chỉnh sửa hồ sơ ipython của bạn ( ~/.ipython/profile_default/ipython_config.py):

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

Mở một trình bao - lưu ý rằng bạn không cần bao gồm --ipython:

python manage.py shell_plus

Bây giờ bất kỳ thứ gì được xác định trong SHELL_PLUS_PRE_IMPORTShoặc SHELL_PLUS_POST_IMPORTS( tài liệu ) sẽ tự động tải xuống!

Lưu ý rằng nếu trình gỡ lỗi của bạn đang ở trình gỡ lỗi (ví dụ pdb.set_trace()) khi bạn lưu tệp, nó có thể cản trở việc tải lại.


1
Cảm ơn bạn đã trả lời. Bạn có thể lưu ý mặc dù, rằng tôi hỏi nó vào năm 2010. Tôi rất vui mừng khi biết rằng sau tám năm tự động tải lại cuối cùng làm việc trong shell_plus :)
Mad Wombat

1

Thay vì chạy các lệnh từ trình bao Django, bạn có thể thiết lập một lệnh quản lý như vậy và chạy lại lệnh đó mỗi lần.


0

Không chính xác những gì bạn muốn, nhưng bây giờ tôi có xu hướng tự xây dựng các lệnh quản lý để thử nghiệm và tìm hiểu mọi thứ.

Trong lệnh, bạn có thể thiết lập một nhóm người dân địa phương theo cách bạn muốn và sau đó thả vào một trình bao tương tác.

import code

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

Không cần tải lại, nhưng là một cách dễ dàng và ít gây phiền nhiễu hơn để kiểm tra tương tác chức năng django.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.