es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Python tiene algún equivalente a los canales de múltiples productores y un consumidor (MPSC) de Rust?

Me gustaría tener una función en Python que cree un par de canal de transmisión / recepción con el mismo o un mecanismo similar al de Rust:

Estos canales tienen dos variantes:

  1. Un canal asincrónico con buffer infinito. La función [channel] devolverá una tupla (Sender, Receiver) en la que todos los envíos serán asincrónicos (no bloqueantes). El canal conceptualmente tiene un buffer infinito.

  2. Un canal sincrónico con límite de capacidad. La función [sync_channel] devolverá una tupla (SyncSender, Receiver) en la que el almacenamiento para los mensajes pendientes es un buffer preasignado de tamaño fijo. Todos los envíos serán sincrónicos, es decir, bloquearán hasta que haya espacio en el buffer disponible. Se permite un límite de 0, lo que hace que el canal se convierta en un canal de “reunión” donde cada remitente entrega atómicamente un mensaje a un receptor.

[channel]: https://doc.rust-lang.org/std/sync/mpsc/fn.channel.html
[sync_channel]: https://doc.rust-lang.org/std/sync/mpsc/fn.sync_channel.html

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para crear una función en Python que cree un par de canal de transmisor/receptor con el mismo o similar mecanismo que Rust, podemos hacer uso del módulo queue, el cual proporciona una implementación segura para hilos de una cola.

    Para un canal asincrónico con buffer infinito, podemos utilizar la clase Queue del módulo queue sin especificar un tamaño máximo, lo cual lo hace infinito. Aquí tienes un ejemplo de implementación:

    import queue
    
    def canal():
        q = queue.Queue()
        return q.put, q.get
    

    La función canal() retorna una tupla de dos funciones, la primera función q.put se utiliza para enviar mensajes al canal y nunca se bloquea, mientras que la segunda función q.get se utiliza para recibir mensajes del canal y se bloquea hasta que haya un mensaje disponible.

    Para un canal síncrono y acotado, podemos utilizar nuevamente la clase Queue, pero esta vez especificaremos un tamaño máximo, lo cual creará un búfer de tamaño fijo. Aquí tienes un ejemplo de implementación:

    import queue
    
    def canal_sincronizado(tamaño=0):
        q = queue.Queue(maxsize=tamaño)
        return q.put, q.get
    

    La función canal_sincronizado() también retorna una tupla de dos funciones, la primera función q.put se utiliza para enviar mensajes al canal y se bloquea hasta que haya espacio en el búfer, y la segunda función q.get se utiliza para recibir mensajes del canal y se bloquea hasta que haya un mensaje disponible.

    Nota que podemos establecer el parámetro tamaño en 0 para crear un canal de encuentro, lo cual hará que cada transmisor entregue atómicamente un mensaje a un receptor.

Comments are closed.