dpkp / kafka-python

Python client for Apache Kafka
http://kafka-python.readthedocs.io/
Apache License 2.0
5.59k stars 1.4k forks source link

Add context manager support to Consumers and producers #1101

Open lyytinen opened 7 years ago

lyytinen commented 7 years ago

Would it make sense for the consumers and producers to implement the context management protocol? So that one could write:

from kafka import KafkaProducer
with KafkaProducer(bootstrap_servers='localhost:1234') as producer:
    for _ in range(100):
        producer.send('foobar', b'some_message_bytes')
tvoinarovskyi commented 7 years ago

Could the producer be entered again? It's just that with DB's it's common to have a pool of connections and with protocol typically is used to acquire 1 connection. Would adding context support not cause confusion like:

global_producer = KafkaProducer(bootstrap_servers='localhost:1234')

def send_message_handler(self, request):
    with global_producer as conn:
        conn.send("foobar", b"some_message_bytes")

And from this example on, the Producer and Consumer are both long running instances, and only in scripts do you create/destroy it in 1 function. Mostly it would be initialized in startup hook and stopped in teardown or something. At least those were my thoughts about not adding it for aiokafka...

lyytinen commented 7 years ago

Fair points. It's true that the use cases that would benefit from context support are marginal but it would still be nice to do those with ease. Not entirely sure about the added confusion also because by using "with" you already acknowledge that something is going to happen behind the curtain.

dpkp commented 7 years ago

fwiw, there is an old (unsupported) context manager in kafka.context that was designed to manage consumer offsets w/ SimpleConsumer.

dpkp commented 6 years ago

Another alternative would be:

import contextlib
from kafka import KafkaProducer

with contextlib.closing(KafkaProducer(bootstrap_servers='localhost:1234')) as producer:
    for _ in range(100):
        producer.send('foobar', b'some_message_bytes')