Maison développement back-end Tutoriel Python 分析Python编程时利用wxPython来支持多线程的方法

分析Python编程时利用wxPython来支持多线程的方法

Jun 06, 2016 am 11:24 AM
python 线程

如果你经常使用python开发GUI程序的话,那么就知道,有时你需要很长时间来执行一个任务。当然,如果你使用命令行程序来做的话,你回非常惊讶。大部分情况下,这会堵塞GUI的事件循环,用户会看到程序卡死。如何才能避免这种情况呢?当然是利用线程或进程了!本文,我们将探索如何使用wxPython和theading模块来实现。

wxpython线程安全方法

wxPython中,有三个“线程安全”的函数。如果你在更新UI界面时,三个函数都不使用,那么你可能会遇到奇怪的问题。有时GUI也忙运行挺正常,有时却会无缘无故的崩溃。因此就需要这三个线程安全的函数:wx.PostEvent, wx.CallAfter和wx.CallLater。据Robin Dunn(wxPython作者)描述,wx.CallAfter使用了wx.PostEvent来给应用程序对象发生事件。应用程序会有个事件处理程序绑定到事件上,并在收到事件后,执行处理程序来做出反应。我认为wx.CallLater是在特定时间后调用了wx.CallAfter函数,已实现规定时间后发送事件。

Robin Dunn还指出Python全局解释锁 (GIL)也会避免多线程同时执行python字节码,这会限制程序使用CPU内核的数量。另外,他还说,“wxPython发布GIL是为了在调用wx API时,其他线程也可以运行”。换句话说,在多核机器上使用多线程,可能效果会不同。

总之,大概的意思是桑wx函数中,wx.CallLater是最抽象的线程安全函数, wx.CallAfter次之,wx.PostEvent是最低级的。下面的实例,演示了如何使用wx.CallAfter和wx.PostEvent函数来更新wxPython程序。

wxPython, Theading, wx.CallAfter and PubSub

wxPython邮件列表中,有些专家会告诉其他人使用wx.CallAfter,并利用PubSub实现wxPython应用程序与其他线程进行通讯,我也赞成。如下代码是具体实现:

import time 
import wx 
   
from threading import Thread 
from wx.lib.pubsub import Publisher 
   
######################################################################## 
class TestThread(Thread): 
  """Test Worker Thread Class."""
   
  #---------------------------------------------------------------------- 
  def __init__(self): 
    """Init Worker Thread Class."""
    Thread.__init__(self) 
    self.start()  # start the thread 
   
  #---------------------------------------------------------------------- 
  def run(self): 
    """Run Worker Thread."""
    # This is the code executing in the new thread. 
    for i in range(6): 
      time.sleep(10) 
      wx.CallAfter(self.postTime, i) 
    time.sleep(5) 
    wx.CallAfter(Publisher().sendMessage, "update", "Thread finished!") 
   
  #---------------------------------------------------------------------- 
  def postTime(self, amt): 
    """
    Send time to GUI
    """
    amtOfTime = (amt + 1) * 10
    Publisher().sendMessage("update", amtOfTime) 
   
######################################################################## 
class MyForm(wx.Frame): 
   
  #---------------------------------------------------------------------- 
  def __init__(self): 
    wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 
   
    # Add a panel so it looks the correct on all platforms 
    panel = wx.Panel(self, wx.ID_ANY) 
    self.displayLbl = wx.StaticText(panel, label="Amount of time since thread started goes here") 
    self.btn = btn = wx.Button(panel, label="Start Thread") 
   
    btn.Bind(wx.EVT_BUTTON, self.onButton) 
   
    sizer = wx.BoxSizer(wx.VERTICAL) 
    sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5) 
    sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 
    panel.SetSizer(sizer) 
   
    # create a pubsub receiver 
    Publisher().subscribe(self.updateDisplay, "update") 
   
  #---------------------------------------------------------------------- 
  def onButton(self, event): 
    """
    Runs the thread
    """
    TestThread() 
    self.displayLbl.SetLabel("Thread started!") 
    btn = event.GetEventObject() 
    btn.Disable() 
   
  #---------------------------------------------------------------------- 
  def updateDisplay(self, msg): 
    """
    Receives data from thread and updates the display
    """
    t = msg.data 
    if isinstance(t, int): 
      self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 
    else: 
      self.displayLbl.SetLabel("%s" % t) 
      self.btn.Enable() 
   
#---------------------------------------------------------------------- 
# Run the program 
if __name__ == "__main__": 
  app = wx.PySimpleApp() 
  frame = MyForm().Show() 
  app.MainLoop()

Copier après la connexion


我们会用time模块来模拟耗时过程,请随意将自己的代码来代替,而在实际项目中,我用来打开Adobe Reader,并将其发送给打印机。这并没什么特别的,但我不用线程的话,应用程序中的打印按钮就会在文档发送过程中卡住,UI界面也会被挂起,直到文档发送完毕。即使一秒,两秒对用户来说都有卡的感觉。

总之,让我们来看看是如何工作的。在我们编写的Thread类中,我们重写了run方法。该线程在被实例化时即被启动,因为我们在__init__方法中有“self.start”代码。run方法中,我们循环6次,每次sheep10秒,然后使用wx.CallAfter和PubSub更新UI界面。循环结束后,我们发送结束消息给应用程序,通知用户。

你会注意到,在我们的代码中,我们是在按钮的事件处理程序中启动的线程。我们还禁用按钮,这样就不能开启多余的线程来。如果我们让一堆线程跑的话,UI界面就会随机的显示“已完成”,而实际却没有完成,这就会产生混乱。对用户来说是一个考验,你可以显示线程PID,来区分线程,你可能要在可以滚动的文本控件中输出信息,这样你就能看到各线程的动向。

最后可能就是PubSub接收器和事件的处理程序了:

def updateDisplay(self, msg): 
  """
  Receives data from thread and updates the display
  """
  t = msg.data 
  if isinstance(t, int): 
    self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 
  else: 
    self.displayLbl.SetLabel("%s" % t) 
    self.btn.Enable()
Copier après la connexion


看我们如何从线程中提取消息,并用来更新界面?我们还使用接受到数据的类型来告诉我们什么显示给了用户。很酷吧?现在,我们玩点相对低级一点点,看wx.PostEvent是如何办的。

wx.PostEvent与线程

下面的代码是基于wxPython wiki编写的,这看起来比wx.CallAfter稍微复杂一下,但我相信我们能理解。

import time 
import wx 
   
from threading import Thread 
   
# Define notification event for thread completion 
EVT_RESULT_ID = wx.NewId() 
   
def EVT_RESULT(win, func): 
  """Define Result Event."""
  win.Connect(-1, -1, EVT_RESULT_ID, func) 
   
class ResultEvent(wx.PyEvent): 
  """Simple event to carry arbitrary result data."""
  def __init__(self, data): 
    """Init Result Event."""
    wx.PyEvent.__init__(self) 
    self.SetEventType(EVT_RESULT_ID) 
    self.data = data 
   
######################################################################## 
class TestThread(Thread): 
  """Test Worker Thread Class."""
   
  #---------------------------------------------------------------------- 
  def __init__(self, wxObject): 
    """Init Worker Thread Class."""
    Thread.__init__(self) 
    self.wxObject = wxObject 
    self.start()  # start the thread 
   
  #---------------------------------------------------------------------- 
  def run(self): 
    """Run Worker Thread."""
    # This is the code executing in the new thread. 
    for i in range(6): 
      time.sleep(10) 
      amtOfTime = (i + 1) * 10
      wx.PostEvent(self.wxObject, ResultEvent(amtOfTime)) 
    time.sleep(5) 
    wx.PostEvent(self.wxObject, ResultEvent("Thread finished!")) 
   
######################################################################## 
class MyForm(wx.Frame): 
   
  #---------------------------------------------------------------------- 
  def __init__(self): 
    wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial") 
   
    # Add a panel so it looks the correct on all platforms 
    panel = wx.Panel(self, wx.ID_ANY) 
    self.displayLbl = wx.StaticText(panel, label="Amount of time since thread started goes here") 
    self.btn = btn = wx.Button(panel, label="Start Thread") 
   
    btn.Bind(wx.EVT_BUTTON, self.onButton) 
   
    sizer = wx.BoxSizer(wx.VERTICAL) 
    sizer.Add(self.displayLbl, 0, wx.ALL|wx.CENTER, 5) 
    sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) 
    panel.SetSizer(sizer) 
   
    # Set up event handler for any worker thread results 
    EVT_RESULT(self, self.updateDisplay) 
   
  #---------------------------------------------------------------------- 
  def onButton(self, event): 
    """
    Runs the thread
    """
    TestThread(self) 
    self.displayLbl.SetLabel("Thread started!") 
    btn = event.GetEventObject() 
    btn.Disable() 
   
  #---------------------------------------------------------------------- 
  def updateDisplay(self, msg): 
    """
    Receives data from thread and updates the display
    """
    t = msg.data 
    if isinstance(t, int): 
      self.displayLbl.SetLabel("Time since thread started: %s seconds" % t) 
    else: 
      self.displayLbl.SetLabel("%s" % t) 
      self.btn.Enable() 
   
#---------------------------------------------------------------------- 
# Run the program 
if __name__ == "__main__": 
  app = wx.PySimpleApp() 
  frame = MyForm().Show() 
  app.MainLoop()

Copier après la connexion


让我们先稍微放一放,对我来说,最困扰的事情是第一块:

# Define notification event for thread completion 
EVT_RESULT_ID = wx.NewId() 
   
def EVT_RESULT(win, func): 
  """Define Result Event."""
  win.Connect(-1, -1, EVT_RESULT_ID, func) 
   
class ResultEvent(wx.PyEvent): 
  """Simple event to carry arbitrary result data."""
  def __init__(self, data): 
    """Init Result Event."""
    wx.PyEvent.__init__(self) 
    self.SetEventType(EVT_RESULT_ID) 
    self.data = data
Copier après la connexion


EVT_RESULT_ID只是一个标识,它将线程与wx.PyEvent和“EVT_RESULT”函数关联起来,在wxPython代码中,我们将事件处理函数与EVT_RESULT进行捆绑,这就可以在线程中使用wx.PostEvent来将事件发送给自定义的ResultEvent了。

结束语

希望你已经明白在wxPython中基本的多线程技巧。还有其他多种多线程方法这里就不在涉及,如wx.Yield和Queues。幸好有wxPython wiki,它涵盖了这些话题,因此如果你有兴趣可以访问wiki的主页,查看这些方法的使用。

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Peut-on exécuter le code sous Windows 8 Peut-on exécuter le code sous Windows 8 Apr 15, 2025 pm 07:24 PM

VS Code peut fonctionner sur Windows 8, mais l'expérience peut ne pas être excellente. Assurez-vous d'abord que le système a été mis à jour sur le dernier correctif, puis téléchargez le package d'installation VS Code qui correspond à l'architecture du système et l'installez comme invité. Après l'installation, sachez que certaines extensions peuvent être incompatibles avec Windows 8 et doivent rechercher des extensions alternatives ou utiliser de nouveaux systèmes Windows dans une machine virtuelle. Installez les extensions nécessaires pour vérifier si elles fonctionnent correctement. Bien que le code VS soit possible sur Windows 8, il est recommandé de passer à un système Windows plus récent pour une meilleure expérience de développement et une meilleure sécurité.

L'extension VScode est-elle malveillante? L'extension VScode est-elle malveillante? Apr 15, 2025 pm 07:57 PM

Les extensions de code vs posent des risques malveillants, tels que la cachette de code malveillant, l'exploitation des vulnérabilités et la masturbation comme des extensions légitimes. Les méthodes pour identifier les extensions malveillantes comprennent: la vérification des éditeurs, la lecture des commentaires, la vérification du code et l'installation avec prudence. Les mesures de sécurité comprennent également: la sensibilisation à la sécurité, les bonnes habitudes, les mises à jour régulières et les logiciels antivirus.

Comment exécuter des programmes dans Terminal Vscode Comment exécuter des programmes dans Terminal Vscode Apr 15, 2025 pm 06:42 PM

Dans VS Code, vous pouvez exécuter le programme dans le terminal via les étapes suivantes: Préparez le code et ouvrez le terminal intégré pour vous assurer que le répertoire de code est cohérent avec le répertoire de travail du terminal. Sélectionnez la commande Run en fonction du langage de programmation (tel que Python de Python your_file_name.py) pour vérifier s'il s'exécute avec succès et résoudre les erreurs. Utilisez le débogueur pour améliorer l'efficacité du débogage.

Choisir entre PHP et Python: un guide Choisir entre PHP et Python: un guide Apr 18, 2025 am 12:24 AM

PHP convient au développement Web et au prototypage rapide, et Python convient à la science des données et à l'apprentissage automatique. 1.Php est utilisé pour le développement Web dynamique, avec une syntaxe simple et adapté pour un développement rapide. 2. Python a une syntaxe concise, convient à plusieurs champs et a un écosystème de bibliothèque solide.

PHP et Python: différents paradigmes expliqués PHP et Python: différents paradigmes expliqués Apr 18, 2025 am 12:26 AM

PHP est principalement la programmation procédurale, mais prend également en charge la programmation orientée objet (POO); Python prend en charge une variété de paradigmes, y compris la POO, la programmation fonctionnelle et procédurale. PHP convient au développement Web, et Python convient à une variété d'applications telles que l'analyse des données et l'apprentissage automatique.

Le code Visual Studio peut-il être utilisé dans Python Le code Visual Studio peut-il être utilisé dans Python Apr 15, 2025 pm 08:18 PM

VS Code peut être utilisé pour écrire Python et fournit de nombreuses fonctionnalités qui en font un outil idéal pour développer des applications Python. Il permet aux utilisateurs de: installer des extensions Python pour obtenir des fonctions telles que la réalisation du code, la mise en évidence de la syntaxe et le débogage. Utilisez le débogueur pour suivre le code étape par étape, trouver et corriger les erreurs. Intégrez Git pour le contrôle de version. Utilisez des outils de mise en forme de code pour maintenir la cohérence du code. Utilisez l'outil de liaison pour repérer les problèmes potentiels à l'avance.

Peut-on utiliser pour mac Peut-on utiliser pour mac Apr 15, 2025 pm 07:36 PM

VS Code est disponible sur Mac. Il a des extensions puissantes, l'intégration GIT, le terminal et le débogueur, et offre également une multitude d'options de configuration. Cependant, pour des projets particulièrement importants ou un développement hautement professionnel, le code vs peut avoir des performances ou des limitations fonctionnelles.

Peut-on rescode exécuter ipynb Peut-on rescode exécuter ipynb Apr 15, 2025 pm 07:30 PM

La clé de l'exécution du cahier Jupyter dans VS Code est de s'assurer que l'environnement Python est correctement configuré, de comprendre que l'ordre d'exécution du code est cohérent avec l'ordre cellulaire et d'être conscient des fichiers volumineux ou des bibliothèques externes qui peuvent affecter les performances. Les fonctions d'achèvement et de débogage du code fournies par VS Code peuvent considérablement améliorer l'efficacité du codage et réduire les erreurs.

See all articles