هل هناك طريقة لفصل مخططات matplotlib بحيث يمكن مواصلة الحساب؟
-
19-08-2019 - |
سؤال
بعد هذه التعليمات في مترجم بايثون، يحصل المرء على نافذة تحتوي على قطعة أرض:
from matplotlib.pyplot import *
plot([1,2,3])
show()
# other code
لسوء الحظ، لا أعرف كيفية الاستمرار في استكشاف الشكل الذي أنشأه بشكل تفاعلي show()
بينما يقوم البرنامج بإجراء المزيد من العمليات الحسابية.
هل هذا من الممكن بأبة طريقة؟في بعض الأحيان تكون الحسابات طويلة وسيكون من المفيد الاستمرار فيها أثناء فحص النتائج المتوسطة.
المحلول
استخدم المكالمات matplotlib
التي لن تمنع:
وعن طريق draw()
:
from matplotlib.pyplot import plot, draw, show
plot([1,2,3])
draw()
print 'continue computation'
# at the end call show to ensure window won't close.
show()
<ع> استخدام طريقة تفاعلية:
from matplotlib.pyplot import plot, ion, show
ion() # enables interactive mode
plot([1,2,3]) # result shows immediatelly (implicit draw())
print 'continue computation'
# at the end call show to ensure window won't close.
show()
نصائح أخرى
استخدم الكلمة الأساسية 'كتلة "لتجاوز السلوك حظر، على سبيل المثال،
from matplotlib.pyplot import show, plot
plot(1)
show(block=False)
# your code
للمتابعة التعليمات البرمجية.
من الأفضل دائمًا التحقق من المكتبة التي تستخدمها إذا كانت تدعم الاستخدام في ملف غير مانع طريق.
ولكن إذا كنت تريد حلاً أكثر عمومية، أو إذا لم تكن هناك طريقة أخرى، فيمكنك تشغيل أي شيء يحظر في عملية منفصلة باستخدام multprocessing
الوحدة المضمنة في بيثون.سيستمر الحساب:
from multiprocessing import Process
from matplotlib.pyplot import plot, show
def plot_graph(*args):
for data in args:
plot(data)
show()
p = Process(target=plot_graph, args=([1, 2, 3],))
p.start()
print 'yay'
print 'computation continues...'
print 'that rocks.'
print 'Now lets wait for the graph be closed to continue...:'
p.join()
ينطوي ذلك على عبء إطلاق عملية جديدة، وفي بعض الأحيان يصعب تصحيح الأخطاء في السيناريوهات المعقدة، لذلك أفضل الحل الآخر (باستخدام matplotlib
'س مكالمات API غير المحظورة)
وحاول
from matplotlib.pyplot import *
plot([1,2,3])
show(block=False)
# other code
# [...]
# Put
show()
# at the very end of your script
# to make sure Python doesn't bail out
# before you finished examining.
الوثائق show()
يقول:
في الوضع غير التبادلي، وعرض كل الأرقام وكتلة حتى يتم إغلاق الأرقام. في الوضع التفاعلي يكون له أي تأثير إلا إذا تم إنشاؤها الأرقام قبل تغيير من غير التبادلي إلى الوضع التفاعلي (غير مستحسن). في هذه الحالة فإنه يعرض الأرقام ولكن لا يمنع.
وهناك حجة الكلمة تجريبية واحدة، block
، قد يتم تعيين لTrue
أو False
لتجاوز السلوك الحجب هو موضح أعلاه.
قد ترغب في قراءة هذه الوثيقة في matplotlib
توثيق بعنوان :
مهم:فقط لتوضيح شيء ما.أفترض أن الأوامر موجودة داخل ملف .py
البرنامج النصي ويتم استدعاء البرنامج النصي باستخدام على سبيل المثال. python script.py
من وحدة التحكم.
الطريقة البسيطة التي تناسبني هي:
- استخدم الكتلة = خطأ داخل العرض: plt.show(كتلة = خطأ)
- يستخدم آخر يعرض() .في نهايةالمطاف من البرنامج النصي .py.
مثال على script.py
ملف:
plt.imshow(*something*)
plt.colorbar()
plt.xlabel("true ")
plt.ylabel("predicted ")
plt.title(" the matrix")
# Add block = False
plt.show(block = False)
################################
# OTHER CALCULATIONS AND CODE HERE ! ! !
################################
# the next command is the last line of my script
plt.show()
في حالتي، كنت أريد أن يكون عدة نوافذ يطفو على السطح كما يتم حسابها. للإشارة، هذه هي الطريقة:
from matplotlib.pyplot import draw, figure, show
f1, f2 = figure(), figure()
af1 = f1.add_subplot(111)
af2 = f2.add_subplot(111)
af1.plot([1,2,3])
af2.plot([6,5,4])
draw()
print 'continuing computation'
show()
وPS. A توجيه إلى matplotlib واجهة OO .
حسنا، كان لدي صعوبة كبيرة في معرفة الأوامر غير مؤمن ... ولكن في النهاية، تمكنت من إعادة صياغة "<لأ href =" http://www.scipy.org/Cookbook/Matplotlib/Animations#head -3d51654b8306b1585664e7fe060a60fc76e5aa08 "يختلط =" noreferrer "> كتاب الطبخ / Matplotlib / الرسوم المتحركة - موحية تحديد عناصر المؤامرة " مثلا، لذلك يعمل مع الخيوط (<م> ويمر البيانات بين المواضيع إما عن طريق المتغيرات العالمية، أو من خلال Pipe
multiprocess م>) على بايثون 2.6.5 على أوبونتو 10.04.
والسيناريو يمكن العثور عليها هنا: <لأ href = "http://sdaaubckp.svn.sourceforge.net/viewvc/sdaaubckp/single-scripts/Animating_selected_plot_elements-thread.py؟revision=101&content-type=text٪2Fplain "يختلط =" noreferrer "> Animating_selected_plot_elements-thread.py - لصق إلا أقل من (<م> مع عدد أقل من تعليقات م>) للرجوع اليها:
import sys
import gtk, gobject
import matplotlib
matplotlib.use('GTKAgg')
import pylab as p
import numpy as nx
import time
import threading
ax = p.subplot(111)
canvas = ax.figure.canvas
# for profiling
tstart = time.time()
# create the initial line
x = nx.arange(0,2*nx.pi,0.01)
line, = ax.plot(x, nx.sin(x), animated=True)
# save the clean slate background -- everything but the animated line
# is drawn and saved in the pixel buffer background
background = canvas.copy_from_bbox(ax.bbox)
# just a plain global var to pass data (from main, to plot update thread)
global mypass
# http://docs.python.org/library/multiprocessing.html#pipes-and-queues
from multiprocessing import Pipe
global pipe1main, pipe1upd
pipe1main, pipe1upd = Pipe()
# the kind of processing we might want to do in a main() function,
# will now be done in a "main thread" - so it can run in
# parallel with gobject.idle_add(update_line)
def threadMainTest():
global mypass
global runthread
global pipe1main
print "tt"
interncount = 1
while runthread:
mypass += 1
if mypass > 100: # start "speeding up" animation, only after 100 counts have passed
interncount *= 1.03
pipe1main.send(interncount)
time.sleep(0.01)
return
# main plot / GUI update
def update_line(*args):
global mypass
global t0
global runthread
global pipe1upd
if not runthread:
return False
if pipe1upd.poll(): # check first if there is anything to receive
myinterncount = pipe1upd.recv()
update_line.cnt = mypass
# restore the clean slate background
canvas.restore_region(background)
# update the data
line.set_ydata(nx.sin(x+(update_line.cnt+myinterncount)/10.0))
# just draw the animated artist
ax.draw_artist(line)
# just redraw the axes rectangle
canvas.blit(ax.bbox)
if update_line.cnt>=500:
# print the timing info and quit
print 'FPS:' , update_line.cnt/(time.time()-tstart)
runthread=0
t0.join(1)
print "exiting"
sys.exit(0)
return True
global runthread
update_line.cnt = 0
mypass = 0
runthread=1
gobject.idle_add(update_line)
global t0
t0 = threading.Thread(target=threadMainTest)
t0.start()
# start the graphics update thread
p.show()
print "out" # will never print - show() blocks indefinitely!
وآمل أن يساعد هذا شخص ما،
هتاف!
في كثير من الحالات هو عليه أكثر ملاءمة حتى حفظ الصورة كملف .png على القرص الصلب.هنا هو السبب:
مزايا:
- يمكنك فتحه وإلقاء نظرة عليه وإغلاقه في أي وقت أثناء العملية.هذا مريح بشكل خاص عندما يعمل تطبيقك لفترة طويلة.
- لا شيء ينبثق ولا تضطر إلى فتح النوافذ.وهذا مناسب بشكل خاص عندما تتعامل مع العديد من الشخصيات.
- يمكن الوصول إلى صورتك للرجوع إليها لاحقًا ولا تضيع عند إغلاق نافذة الشكل.
عائق:
- الشيء الوحيد الذي يمكنني التفكير فيه هو أنه سيتعين عليك البحث عن المجلد وفتح الصورة بنفسك.
إذا كنت تعمل في وحدة التحكم، أي IPython
هل يمكن استخدام plt.show(block=False)
كما أشار في إجابات أخرى. ولكن إذا كنت كسول يمكنك كتابة فقط:
plt.show(0)
والتي سوف تكون هي نفسها.
وكان لي أيضا أن أضيف plt.pause(0.001)
إلى رمز جهدي لجعل حقا انها تعمل داخل لحلقة (وإلا فإنه سوف تظهر فقط المؤامرة الأولى والأخيرة):
import matplotlib.pyplot as plt
plt.scatter([0], [1])
plt.draw()
plt.show(block=False)
for i in range(10):
plt.scatter([i], [i+1])
plt.draw()
plt.pause(0.001)
وأردت أيضا بلدي المؤامرات لعرضه تشغيل بقية رمز (وبعدها يطلع على عرض) حتى إذا كان هناك خطأ (أنا في بعض الأحيان استخدام المؤامرات من أجل التصحيح). I مشفرة يصل هذا الإختراق قليلا بحيث أن أي مؤامرات داخل بيان with
هذا تتصرف على هذا النحو.
وهذا هو على الارجح قليلا جدا غير قياسي وغير المستحسن لرمز الإنتاج. وربما هناك الكثير من "gotchas" مخبأة في هذا القانون.
from contextlib import contextmanager
@contextmanager
def keep_plots_open(keep_show_open_on_exit=True, even_when_error=True):
'''
To continue excecuting code when plt.show() is called
and keep the plot on displaying before this contex manager exits
(even if an error caused the exit).
'''
import matplotlib.pyplot
show_original = matplotlib.pyplot.show
def show_replacement(*args, **kwargs):
kwargs['block'] = False
show_original(*args, **kwargs)
matplotlib.pyplot.show = show_replacement
pylab_exists = True
try:
import pylab
except ImportError:
pylab_exists = False
if pylab_exists:
pylab.show = show_replacement
try:
yield
except Exception, err:
if keep_show_open_on_exit and even_when_error:
print "*********************************************"
print "Error early edition while waiting for show():"
print "*********************************************"
import traceback
print traceback.format_exc()
show_original()
print "*********************************************"
raise
finally:
matplotlib.pyplot.show = show_original
if pylab_exists:
pylab.show = show_original
if keep_show_open_on_exit:
show_original()
# ***********************
# Running example
# ***********************
import pylab as pl
import time
if __name__ == '__main__':
with keep_plots_open():
pl.figure('a')
pl.plot([1,2,3], [4,5,6])
pl.plot([3,2,1], [4,5,6])
pl.show()
pl.figure('b')
pl.plot([1,2,3], [4,5,6])
pl.show()
time.sleep(1)
print '...'
time.sleep(1)
print '...'
time.sleep(1)
print '...'
this_will_surely_cause_an_error
إذا / عندما تنفيذ السليم "الحفاظ على المؤامرات مفتوحة (حتى في حالة حدوث خطأ) والسماح المؤامرات الجديدة التي سيتم عرضها"، وأود أن تريد البرنامج النصي لصحيح الخروج إذا لم تدخل المستخدم يقول خلاف ذلك (لتنفيذ دفعة الأغراض).
وأنا قد تستخدم ما يشبه المهلة-السؤال: "نهاية البرنامج النصي \ n اضغط ص إذا كنت تريد إخراج بالتخطيط ليكون مؤقتا (لديك 5 ثوان):" من <لأ href = "HTTPS: // ستاكوفيرفلوو كوم / الأسئلة / 26704840 / الزاوية الحالات مقابل بلدي الانتظار مقابل المستخدم المدخلات وتوقف التنفيذ "> https://stackoverflow.com/questions/26704840/corner-cases-for-my-wait- مقابل المستخدم المدخلات وتوقف التنفيذ .
في برنامجي النظام () لا يمنع، على الرغم من أنني أرغب في السيناريو الانتظار للمستخدم التفاعل مع الرسم البياني (وجمع البيانات باستخدام الاسترجاعات "pick_event ') قبل المتابعة.
في أجل منع تنفيذ حتى يتم إغلاق نافذة المؤامرة، واعتدت ما يلي:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x,y)
# set processing to continue when window closed
def onclose(event):
fig.canvas.stop_event_loop()
fig.canvas.mpl_connect('close_event', onclose)
fig.show() # this call does not block on my system
fig.canvas.start_event_loop_default() # block here until window closed
# continue with further processing, perhaps using result from callbacks
ملحوظة، مع ذلك، أن canvas.start_event_loop_default () ينتج التحذير التالي:
C:\Python26\lib\site-packages\matplotlib\backend_bases.py:2051: DeprecationWarning: Using default event loop until function specific to this GUI is implemented
warnings.warn(str,DeprecationWarning)
وعلى الرغم من أن السيناريو لا يزال يدير.
plt.figure(1)
plt.imshow(your_first_image)
plt.figure(2)
plt.imshow(your_second_image)
plt.show(block=False) # That's important
raw_input("Press ENTER to exist") # Useful when you run your Python script from the terminal and you want to hold the running to see your figures until you press Enter
في رأيي، والأجوبة في هذا الموضوع توفر الأساليب التي لا تعمل من أجل كل النظم وفي حالات أكثر تعقيدا مثل الرسوم المتحركة. أقترح أن نلقي نظرة على إجابة لMiKTeX في الموضوع التالي، حيث تم العثور على وسيلة قوية: كيفية الانتظار حتى ينتهي matplotlib الرسوم المتحركة؟
إذا كنت ترغب في فتح شخصيات متعددة، مع إبقائها فتح كل شيء، عملت هذا الرمز بالنسبة لي:
show(block=False)
draw()
ووOP يسأل عن detatching المؤامرات matplotlib
. تفترض معظم الإجابات تنفيذ الأمر من خلال مترجم الثعبان. وحدة استخدام المعروضة هنا هي تفضيل بلدي لرمز اختبار في محطة (على سبيل المثال باش) حيث يتم تشغيل file.py
وتريد مؤامرة (ق) من أجل التوصل إلى ولكن السيناريو الثعبان لاستكمال والعودة إلى موجه الأوامر.
وهذا ملف مستقل يستخدم multiprocessing
لإطلاق عملية منفصلة بتهمة التآمر مع البيانات matplotlib
. مخارج موضوع الرئيسية باستخدام os._exit(1)
المذكورة في هذا آخر . قوات os._exit()
الرئيسية للخروج ولكنه يترك عملية طفل matplotlib
على قيد الحياة واستجابة حتى يتم إغلاق نافذة المؤامرة. انها عملية منفصلة تماما.
وهذا النهج هو قليلا مثل جلسة تطوير ماتلاب مع نوافذ شخصية التي تأتي مع موجه الأوامر استجابة. مع هذا النهج، كنت قد فقدت كل اتصال مع عملية نافذة الشكل، ولكن، وهذا موافق لتطوير وتصحيح الأخطاء. مجرد إغلاق نافذة والحفاظ على الاختبار.
تم تصميم multiprocessing
لتنفيذ الثعبان فقط كود مما يجعله ربما يكون أكثر ملاءمة من subprocess
. multiprocessing
هو عبر منصة هذا ما ينبغي أن تعمل بشكل جيد في ويندوز أو ماكنتوش مع تعديل ضئيلة أو معدومة. ليست هناك حاجة للتحقق من نظام التشغيل الأساسي. تم اختبار هذا على لينكس، أوبونتو 18.04LTS.
#!/usr/bin/python3
import time
import multiprocessing
import os
def plot_graph(data):
from matplotlib.pyplot import plot, draw, show
print("entered plot_graph()")
plot(data)
show() # this will block and remain a viable process as long as the figure window is open
print("exiting plot_graph() process")
if __name__ == "__main__":
print("starting __main__")
multiprocessing.Process(target=plot_graph, args=([1, 2, 3],)).start()
time.sleep(5)
print("exiting main")
os._exit(0) # this exits immediately with no cleanup or buffer flushing
وتشغيل file.py
إحضار نافذة الرقم، ثم __main__
مخارج لكن يبقى نافذة multiprocessing
+ الرقم matplotlib
استجابة مع التكبير، والقومية، والأزرار الأخرى لأنها عملية مستقلة.
والتحقق من العمليات في موجه الأوامر باش مع:
وps ax|grep -v grep |grep file.py
استخدم plt.show(block=False)
، وفي نهاية الخاص بك plt.show()
دعوة النصي.
وهذا سيضمن أن الإطار لن تكون مغلقة عند الانتهاء من البرنامج النصي.