<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def producer_consumer(producer, consumer, addr='tcp://127.0.0.1', port=None, context=None):
 """A producer-consumer pattern. Parameters producer : callable Callable that takes a single argument, a handle for a ZeroMQ PUSH socket. Must be picklable. consumer : callable Callable that takes a single argument, a handle for a ZeroMQ PULL socket. addr : str, optional Address to which the socket should connect. Defaults to localhost ('tcp://127.0.0.1'). port : int, optional The port on which the consumer should listen. context : zmq.Context, optional The ZeroMQ Context to use. One will be created otherwise. Returns ------- result Passes along whatever `consumer` returns. Notes ----- This sets up a PULL socket in the calling process and forks a process that calls `producer` on a PUSH socket. When the consumer returns, the producer process is terminated. Wrap `consumer` or `producer` in a `functools.partial` object in order to send additional arguments; the callables passed in should expect only one required, positional argument, the socket handle. """

    context_created = False
    if context is None:
        context_created = True
        context = zmq.Context()
    try:
        consumer_socket = context.socket(zmq.PULL)
        if port is None:
            port = consumer_socket.bind_to_random_port(addr)
        try:
            process = _spawn_producer(producer, port)
            result = consumer(consumer_socket)
        finally:
            process.terminate()
        return result
    finally:
        # Works around a Python 3.x bug.
        if context_created:
            context.destroy()