การโหลด submodules ใหม่ใน IPython


363

ขณะนี้ฉันกำลังทำงานกับโครงการงูหลามที่มีโมดูลย่อยและใช้ numpy / scipy Ipython ใช้เป็นคอนโซลแบบโต้ตอบ น่าเสียดายที่ฉันไม่ได้มีความสุขกับเวิร์กโฟลว์ที่ฉันใช้อยู่ตอนนี้ฉันจะขอบคุณคำแนะนำบางอย่าง

ใน IPython เฟรมเวิร์กจะถูกโหลดโดยimportคำสั่งง่าย ๆ อย่างไรก็ตามบ่อยครั้งที่จำเป็นต้องเปลี่ยนรหัสในหนึ่งใน submodules ของกรอบงาน ณ จุดนี้รุ่นโหลดแล้วและฉันใช้ IPython เพื่อโต้ตอบกับมัน

ตอนนี้เฟรมเวิร์กประกอบด้วยโมดูลจำนวนมากที่ขึ้นอยู่กับแต่ละอื่น ๆ เช่นเมื่อเฟรมเวิร์กถูกโหลดครั้งแรกโมดูลหลักกำลังอิมพอร์ตและกำหนดค่า submodules reload(main_mod.sub_mod)การเปลี่ยนแปลงรหัสที่จะดำเนินการเฉพาะในกรณีที่โมดูลจะโหลดใหม่โดยใช้ สิ่งนี้ยุ่งยากเนื่องจากฉันต้องโหลดโมดูลที่เปลี่ยนใหม่ทั้งหมดทีละตัวโดยใช้พา ธ เต็ม มันจะสะดวกมากถ้าreload(main_module)จะโหลดโมดูลย่อยทั้งหมดอีกครั้ง แต่ไม่มีการโหลด numpy / scipy ..


คุณสนใจที่จะอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับHowever, it is often necessary to change code in one of the submodules of the framework.ทำไมnecessary to change codeหรือไม่ ขอบคุณ
กิน

16
@eat: เฟรมเวิร์กกำลังได้รับการพัฒนาอย่างต่อเนื่องดังนั้นจึงมีการเปลี่ยนแปลงฐานรหัสอย่างต่อเนื่อง
Alain

คำตอบ:


531

IPython มาพร้อมกับการรีโหลดเวทมนตร์อัตโนมัติ :

%load_ext autoreload
%autoreload 2

มันจะโหลดโมดูลที่เปลี่ยนแปลงทั้งหมดใหม่ทุกครั้งก่อนที่จะเรียกใช้งานบรรทัดใหม่ dreloadวิธีการทำงานนี้จะแตกต่างออกไปเล็กน้อย คำเตือนบางอย่างใช้พิมพ์%autoreload?เพื่อดูสิ่งที่ผิดพลาด


หากคุณต้องการเปิดใช้งานการตั้งค่านี้อยู่เสมอให้แก้ไขไฟล์การกำหนดค่า IPython ของคุณ~/.ipython/profile_default/ipython_config.py[1] และต่อท้าย:

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

เครดิตให้กับ @Kos ผ่านทางความคิดเห็นด้านล่าง

[1] หากคุณไม่มีไฟล์~/.ipython/profile_default/ipython_config.pyคุณต้องโทรipython profile createก่อน $IPYTHONDIRหรือไฟล์อาจจะอยู่ที่


63
ฉันมีc.InteractiveShellApp.extensions = ['autoreload']และในของฉันc.InteractiveShellApp.exec_lines = ['%autoreload 2'] ~/.ipython/profile_default/ipython_config.py
Kos

4
แต่นั่นอาจเป็นผลงานที่มีประสิทธิภาพ แต่ควรใช้ด้วยความระมัดระวัง
asmeurer

3
การรีโหลดจะดำเนินการเฉพาะเมื่อคุณกด Enter ในเปลือก Ipython และโดยปกติจะไม่สามารถสังเกตเห็นได้
pv

3
วิธีนี้ใช้งานได้ดีเมื่อทำการดีบั๊กแพคเกจดังนั้นอะไรคือจุดประสงค์ของการโหลด dreload ดูเหมือนว่า dreload นั้นจะรุกรานและพิมพ์ข้อผิดพลาดเมื่อแพ็กเกจบางอย่างเช่น matplotlib ถูกโหลด
dashesy

3
หากคุณใช้วิธีการ @Kos ตรวจสอบให้แน่ใจว่ามีการกำหนด c: c = get_config ()
Tickon

27

ใน IPython 0.12 (และอาจเร็วกว่านี้) คุณสามารถใช้สิ่งนี้:

%load_ext autoreload
%autoreload 2

นี่เป็นหลักเหมือนกับคำตอบโดย pv %load_extยกเว้นว่าส่วนขยายที่ได้รับการเปลี่ยนชื่อและมีการโหลดตอนนี้ใช้


20

ด้วยเหตุผลบางอย่างไม่%autoreloadหรือdreloadดูเหมือนจะทำงานสำหรับสถานการณ์เมื่อคุณนำเข้ารหัสจากโน้ตบุ๊คหนึ่งไปยังอีก งูหลามธรรมดาเท่านั้นที่reloadทำงาน:

reload(module)

อ้างอิงจาก[1]


10
ใน Python 3.4+ คุณสามารถค้นหาการรีโหลดได้ในโมดูล importlib ดูคำถามนี้
Praveen

1
วิธีนี้ใช้ได้เมื่อเพิ่มวิธีอินสแตนซ์ซึ่งไม่เหมือนกับ%autoreloadเทคนิค มีรายงานบั๊กแบบเปิดเพื่อเพิ่มการสนับสนุน%autoreloadสำหรับสิ่งนี้ .
ijoseph

18

IPython นำเสนอdreload()การโหลดซ้ำทั้งหมดซ้ำทั้งหมด โดยส่วนตัวแล้วฉันชอบที่จะใช้%run()คำสั่งเวทย์มนตร์ (แม้ว่ามันจะไม่ได้ทำการรีโหลดลึกตามที่ John Salvatier ชี้ให้เห็นในการแสดงความคิดเห็น)


11
ฉันคิดว่า (น่าเสียดายที่) เรียกใช้ script.py โหลดสคริปต์ที่คุณโทรใหม่เท่านั้นไม่ใช่แพ็คเกจที่นำเข้า หากคุณกำลังพยายามที่จะแก้ไขข้อบกพร่องแพคเกจที่คุณกำลังสร้างนี้อาจเป็นความเจ็บปวด
John Salvatier

2
NB dreloadได้ถูกแทนที่ใน IPython ที่ผ่านมา (เช่น IPython 6.0) โดยdeepreload
dan mackinlay

8

ชื่อโมดูลimportlibอนุญาตให้เข้าถึงการนำเข้า internals โดยเฉพาะอย่างยิ่งมันมีฟังก์ชั่นimportlib.reload():

import importlib
importlib.reload(my_module)

ในทางตรงกันข้ามของ%autoreload, importlib.reload()นอกจากนี้ยังมีการตั้งค่าตัวแปรทั่วโลกตั้งอยู่ในโมดูล ในกรณีส่วนใหญ่มันเป็นสิ่งที่คุณต้องการ

importlibมีให้ตั้งแต่ Python 3.1 เท่านั้น impสำหรับรุ่นเก่าที่คุณต้องใช้โมดูล


โซลูชั่นเดียวที่ทำงานสำหรับฉัน
gustavz

5

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

เพื่อหลีกเลี่ยงการพิมพ์ฟังก์ชั่นเวทย์มนตร์เหล่านั้นซ้ำแล้วซ้ำอีกพวกเขาสามารถใส่ในสคริปต์เริ่มต้น ipython (ชื่อด้วยคำต่อท้าย. py ภายใต้. ipython / profile_default / startup สคริปต์ไพ ธ อนทั้งหมดภายใต้โฟลเดอร์นั้นจะโหลดตามลำดับคำศัพท์) ดูเหมือนว่าต่อไปนี้:

from IPython import get_ipython
ipython = get_ipython()

ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")

สิ่งนี้จะทำงานได้เช่นกันหากคุณใช้งานสคริปต์ของคุณเช่น%run script.pyจาก IPython REPL
Patrick Sanan

3

เกี่ยวกับสิ่งนี้:

import inspect

# needs to be primed with an empty set for loaded
def recursively_reload_all_submodules(module, loaded=None):
    for name in dir(module):
        member = getattr(module, name)
        if inspect.ismodule(member) and member not in loaded:
            recursively_reload_all_submodules(member, loaded)
    loaded.add(module)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

การทำเช่นนี้ควรรีโหลดต้นไม้ทั้งหมดของโมดูลและส่งข้อมูลที่คุณให้ คุณยังสามารถใส่ฟังก์ชั่นนี้ใน. ipythonrc ของคุณ (ฉันคิดว่า) ดังนั้นมันจึงโหลดทุกครั้งที่คุณเริ่มล่าม


ที่ดูดี แต่ก็อาจเป็นไปได้ว่ามันจะไม่ครอบคลุมโมดูลหรือสมาชิกของโมดูลที่จะถูกนำเข้าใช้หรือfrom ... import ... import ... asอย่างน้อยก็ทำให้ฉันมีปัญหาบางอย่างเมื่อทำงานแบบโต้ตอบบนเครื่อง ฉันย้ายไปใช้มาโครที่เก็บไว้ใน IPython ซึ่งทำหน้าที่นำเข้าและตั้งค่าที่จำเป็นเพื่อเริ่มทำงานในสถานะที่กำหนดไว้ล่วงหน้า
Bernhard

จริง ๆ แล้วมันครอบคลุมfrom ... import ...และimport ... asตราบใดที่สิ่งที่คุณนำเข้าเป็นโมดูล สิ่งเดียวที่ไม่ครอบคลุมคือโมดูลในแพ็คเกจที่ไม่ได้โหลดจาก__init__.pyไฟล์ สำหรับแพ็คเกจคุณอาจตรวจสอบว่า__path__แอตทริบิวต์ของโมดูลเป็นไดเรกทอรีหรือไม่ ถ้าเป็นก็ให้สำรวจและนำเข้าโมดูลทั้งหมดที่คุณสามารถหาได้ซ้ำ ๆ ฉันไม่ได้เขียนส่วนนี้เพราะผู้เขียนไม่ได้ขอวิธีแก้ไขสำหรับแพ็คเกจ
YH วงศ์

แน่นอนนี้ดูดี ฉันคิดเกี่ยวกับความเป็นไปได้นี้ในเวลาเดียวกันผมจะคาดหวังว่าจะมีบางส่วนที่สร้างขึ้นในการทำงานเช่นอยู่บนพื้นฐานนี้ อย่างไรก็ตามฉันไม่ทราบวิธีการใช้งาน หลังจากขุดบางส่วนที่ควรเกิดขึ้นก่อนที่ฉันจะโพสต์คำถามเดิมฉันพบส่วนขยายนี้
Alain

นอกจากนี้คุณสามารถใช้pkgutilเพื่อรับ submodules ทั้งหมดในแพ็คเกจแม้ว่าแพคเกจจะไม่นำเข้า submodules ลงในโมดูลด้านบน stackoverflow.com/a/1707786/1243926
osa

คุณต้องทำ: สำหรับโมดูลในsys.modules:
aoeu256

2

ตัวเลือกอื่น:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

ตรวจสอบแล้วบน ipython และ ipython3 v5.1.0 บน Ubuntu 14.04


1

วิธีปฏิบัติมาตรฐานของฉันสำหรับการโหลดซ้ำคือการรวมทั้งสองวิธีหลังจากการเปิดครั้งแรกIPython:

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

reload(module_name)โมดูลโหลดก่อนที่จะทำเช่นนี้จะทำให้พวกเขาไม่ได้ที่จะโหลดใหม่แม้จะมีคู่มือ ฉันยังไม่ค่อยได้รับปัญหาที่อธิบายไม่ได้กับวิธีการเรียนไม่โหลดใหม่ที่ฉันยังไม่ได้ดู


1

โปรดทราบว่าสิ่งที่กล่าวมาข้างต้นautoreloadใช้งานได้เฉพาะใน IntelliJ หากคุณบันทึกไฟล์ที่เปลี่ยนแปลงด้วยตนเอง (เช่นใช้ ctrl + s หรือ cmd + s) ดูเหมือนจะไม่ทำงานกับการบันทึกอัตโนมัติ


ฉันยืนยันกรณีนี้สำหรับ PyCharm ด้วย
tsando

0

ในสมุดบันทึก Jupyter บน Anaconda ให้ทำสิ่งนี้:

%load_ext autoreload
%autoreload 2

ผลิตข้อความ:

ส่วนขยายโหลดอัตโนมัติโหลดแล้ว ในการโหลดซ้ำให้ใช้: %reload_ext autoreload

ดูเหมือนว่าจะทำดีกว่า:

%reload_ext autoreload
%autoreload 2

ข้อมูลรุ่น:

เวอร์ชันของเซิร์ฟเวอร์โน้ตบุ๊กคือ 5.0.0 และทำงานบน: Python 3.6.2 | Anaconda, Inc. | (ค่าเริ่มต้น, 20 ก.ย. 2017, 13:35:58) [MSC v.1900 32 บิต (Intel)]


0

subobjects ใด ๆ จะไม่ถูกโหลดใหม่ด้วยสิ่งนี้ฉันเชื่อว่าคุณต้องใช้โหลดดีพีไอของ IPython

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.