usar tutorial español creator convertir con archivo python multithreading pyqt

tutorial - Enhebrado en una aplicación PyQt: ¿usar subprocesos Qt o subprocesos Python?



qt python tutorial (7)

Esto fue discussed no hace mucho tiempo en la lista de correo de PyQt. Citando los comments Giovanni Bajo sobre el tema:

Es casi lo mismo. La principal diferencia es que QThreads está mejor integrado con Qt (señales / ranuras asincrónicas, bucle de eventos, etc.). Además, no puede usar Qt desde un hilo de Python (no puede, por ejemplo, publicar un evento en el hilo principal a través de QApplication.postEvent): necesita un QThread para que funcione.

Una regla general podría ser utilizar QThreads si va a interactuar de alguna manera con Qt, y usar hilos de Python de lo contrario.

Y algunos comentarios anteriores sobre este tema del autor de PyQt: "ambos son envoltorios alrededor de las mismas implementaciones de subprocesos nativos". Y ambas implementaciones usan GIL de la misma manera.

Estoy escribiendo una aplicación GUI que regularmente recupera datos a través de una conexión web. Dado que esta recuperación lleva un tiempo, esto hace que la IU no responda durante el proceso de recuperación (no se puede dividir en partes más pequeñas). Es por eso que me gustaría externalizar la conexión web a un hilo de trabajo por separado.

[Sí, lo sé, ahora tengo dos problemas .]

De todos modos, la aplicación usa PyQt4, por lo que me gustaría saber cuál es la mejor opción: ¿usar subprocesos de Qt o usar el módulo de threading Python? ¿Cuáles son las ventajas / desventajas de cada uno? ¿O tienes una sugerencia totalmente diferente?

Edit (re bounty): Si bien la solución en mi caso particular probablemente usará una solicitud de red no bloqueante como sugirieron Jeff Ober y Lukáš Lalinský (por lo tanto, básicamente dejando los problemas de concurrencia a la implementación de red), aún me gustaría tener más. respuesta en profundidad a la pregunta general:

¿Cuáles son las ventajas y desventajas de utilizar los hilos de PyQt4 (es decir, Qt) sobre los hilos de Python nativos (desde el módulo de threading )?

Edición 2: Gracias a todos por sus respuestas. Aunque no hay un acuerdo del 100%, parece haber consenso generalizado de que la respuesta es "usar Qt", ya que la ventaja de esto es la integración con el resto de la biblioteca, sin causar desventajas reales.

Para cualquiera que desee elegir entre las dos implementaciones de subprocesamiento, recomiendo leer todas las respuestas proporcionadas aquí, incluido el hilo de la lista de correo de PyQt al que abbot vincula.

Hubo varias respuestas que consideré para la recompensa; al final, elegí el abad para la referencia externa muy relevante; fue, sin embargo, una llamada cercana.

Gracias de nuevo.


Jeff tiene algunos puntos buenos. Solo un hilo principal puede hacer cualquier actualización GUI. Si necesita actualizar la GUI desde el hilo, las señales de conexión en cola de Qt-4 facilitan el envío de datos a través de los hilos y se invocarán automáticamente si está utilizando QThread; No estoy seguro de si lo estarán si usa subprocesos de Python, aunque es fácil agregar un parámetro a connect() .


La ventaja de QThread es que está integrado con el resto de la biblioteca de Qt. Es decir, los métodos de thread-aware en Qt necesitarán saber en qué thread se ejecutan, y para mover objetos entre hilos, necesitarás usar QThread . Otra característica útil es ejecutar su propio bucle de evento en un hilo.

Si está accediendo a un servidor HTTP, debe considerar QNetworkAccessManager .


Los subprocesos de Python serán más simples y seguros, y dado que se trata de una aplicación basada en E / S, pueden eludir el GIL. Dicho esto, ¿ha considerado las E / S sin bloqueo usando conectores / selectos Twisted o non-blocking?

EDITAR: más sobre hilos

Hilos de Python

Los hilos de Python son hilos del sistema. Sin embargo, Python usa un bloqueo de intérprete global (GIL) para garantizar que el intérprete solo ejecute un cierto bloque de tamaño de instrucciones de código byte a la vez. Afortunadamente, Python libera el GIL durante las operaciones de entrada / salida, lo que hace que los subprocesos sean útiles para simular E / S sin bloqueo.

Advertencia importante: Esto puede ser engañoso, ya que el número de instrucciones de código de bytes no se corresponde con el número de líneas en un programa. Incluso una única tarea puede no ser atómica en Python, por lo que es necesario un bloqueo mutex para cualquier bloque de código que deba ejecutarse atómicamente, incluso con el GIL.

Hilos de QT

Cuando Python transfiere el control a un módulo compilado de un tercero, libera el GIL. Se convierte en responsabilidad del módulo garantizar la atomicidad cuando sea necesario. Cuando se pase el control, Python usará el GIL. Esto puede hacer que el uso de bibliotecas de terceros junto con hilos confunda. Es aún más difícil utilizar una biblioteca de threading externa porque agrega incertidumbre en cuanto a dónde y cuándo el control está en manos del módulo frente al intérprete.

Los subprocesos de QT funcionan con el GIL liberado. Los subprocesos de QT pueden ejecutar código de biblioteca de QT (y otro código de módulo compilado que no adquiere el GIL) al mismo tiempo. Sin embargo, el código Python ejecutado dentro del contexto de un subproceso QT aún adquiere el GIL, y ahora debe administrar dos conjuntos de lógica para bloquear el código.

Al final, tanto los hilos QT como los hilos Python son envoltorios alrededor de los hilos del sistema. Los subprocesos de Python son marginalmente más seguros de usar, ya que las partes que no están escritas en Python (implícitamente usando el GIL) usan el GIL en cualquier caso (aunque la advertencia anterior todavía se aplica).

E / S sin bloqueo

Los hilos agregan una complejidad extraordinaria a su aplicación. Especialmente cuando se trata de la interacción ya compleja entre el intérprete de Python y el código del módulo compilado. Mientras que muchos encuentran difícil de seguir la programación basada en eventos, la E / S no bloqueante basada en eventos a menudo es mucho menos difícil de razonar que los hilos.

Con las E / S asíncronas, siempre puede estar seguro de que, para cada descriptor abierto, la ruta de ejecución es coherente y ordenada. Hay, obviamente, problemas que deben abordarse, como qué hacer cuando el código que depende de un canal abierto depende además de los resultados del código que se llamará cuando otro canal abierto devuelva datos.

Una buena solución para E / S sin bloqueo basadas en eventos es la nueva biblioteca de Diesel . Está restringido a Linux en este momento, pero es extraordinariamente rápido y bastante elegante.

También vale la pena su tiempo para aprender pyevent , un contenedor de la maravillosa biblioteca libevent, que proporciona un marco básico para la programación basada en eventos utilizando el método más rápido disponible para su sistema (determinado en tiempo de compilación).


Me hice la misma pregunta cuando estaba trabajando para PyTalk .

Si está utilizando Qt, necesita usar QThread para poder usar el marco de Qt y, especialmente, el sistema de señal / ranura.

Con el motor de señal / ranura, podrá hablar de un hilo a otro y con cada parte de su proyecto.

Además, no hay una pregunta de rendimiento sobre esta elección ya que ambas son uniones de C ++.

Aquí está mi experiencia de PyQt y thread.

Te animo a usar QThread .


No puedo comentar las diferencias exactas entre los subprocesos de Python y PyQt, pero he estado haciendo lo que está intentando hacer usando QThread , QNetworkAcessManager y asegurándose de llamar a QApplication.processEvents() mientras el hilo está activo. Si la capacidad de respuesta de la GUI es realmente el problema que está tratando de resolver, lo último lo ayudará.


Tampoco puedo recomendarlo, pero puedo intentar describir las diferencias entre los subprocesos CPython y Qt.

En primer lugar, los hilos CPython no se ejecutan al mismo tiempo, al menos no el código Python. Sí, crean subprocesos del sistema para cada subproceso de Python, sin embargo, solo se permite ejecutar el subproceso que tiene Global Interpreter Lock (las extensiones C y el código FFI pueden omitirlo, pero el bytecode de Python no se ejecuta mientras el subproceso no contiene GIL).

Por otro lado, tenemos subprocesos Qt, que básicamente son subprocesos comunes de capa sobre sistema, no tienen bloqueo de intérprete global y, por lo tanto, son capaces de ejecutarse simultáneamente. No estoy seguro de cómo PyQt se ocupa de esto, sin embargo, a menos que sus subprocesos Qt llamen al código Python, deberían poder ejecutarse al mismo tiempo (bloquee varios bloqueos adicionales que podrían implementarse en varias estructuras).

Para un ajuste fino adicional, puede modificar la cantidad de instrucciones de código de bytes que se interpretan antes de cambiar la propiedad de GIL; valores más bajos significan más cambio de contexto (y posiblemente mayor capacidad de respuesta) pero menor rendimiento por hilo individual (los interruptores de contexto tienen su costo). intente cambiar cada pocas instrucciones, no ayuda a acelerar).

Espero que ayude con tus problemas :)