def runcp_producer_loop(<EOL>lightcurve_list,<EOL>input_queue,<EOL>input_bucket,<EOL>result_queue,<EOL>result_bucket,<EOL>pfresult_list=None,<EOL>runcp_kwargs=None,<EOL>process_list_slice=None,<EOL>purge_queues_when_done=False,<EOL>delete_queues_when_done=False,<EOL>download_when_done=True,<EOL>save_state_when_done=True,<EOL>s3_client=None,<EOL>sqs_client=None<EOL>):
if not sqs_client:<EOL><INDENT>sqs_client = boto3.client('<STR_LIT>')<EOL><DEDENT>if not s3_client:<EOL><INDENT>s3_client = boto3.client('<STR_LIT>')<EOL><DEDENT>if isinstance(lightcurve_list, str) and os.path.exists(lightcurve_list):<EOL><INDENT>with open(lightcurve_list, '<STR_LIT:r>') as infd:<EOL><INDENT>lclist = infd.readlines()<EOL><DEDENT>lclist = [x.replace('<STR_LIT:\n>','<STR_LIT>') for x in lclist if len(x) > <NUM_LIT:0>]<EOL>if process_list_slice is not None:<EOL><INDENT>lclist = lclist[process_list_slice[<NUM_LIT:0>]:process_list_slice[<NUM_LIT:1>]]<EOL><DEDENT>lclist = [x[<NUM_LIT:1>:] for x in lclist if x.startswith('<STR_LIT:/>')]<EOL>lclist = ['<STR_LIT>' % (input_bucket, x) for x in lclist]<EOL><DEDENT>elif isinstance(lightcurve_list, list):<EOL><INDENT>lclist = lightcurve_list<EOL><DEDENT>try:<EOL><INDENT>inq = sqs_client.get_queue_url(QueueName=input_queue)<EOL>inq_url = inq['<STR_LIT>']<EOL>LOGINFO('<STR_LIT>')<EOL><DEDENT>except ClientError as e:<EOL><INDENT>inq = awsutils.sqs_create_queue(input_queue, client=sqs_client)<EOL>inq_url = inq['<STR_LIT:url>']<EOL><DEDENT>try:<EOL><INDENT>outq = sqs_client.get_queue_url(QueueName=result_queue)<EOL>outq_url = outq['<STR_LIT>']<EOL>LOGINFO('<STR_LIT>')<EOL><DEDENT>except ClientError as e:<EOL><INDENT>outq = awsutils.sqs_create_queue(result_queue, client=sqs_client)<EOL>outq_url = outq['<STR_LIT:url>']<EOL><DEDENT>LOGINFO('<STR_LIT>' % inq_url)<EOL>LOGINFO('<STR_LIT>' % outq_url)<EOL>LOGINFO('<STR_LIT>')<EOL>time.sleep(<NUM_LIT>)<EOL>if pfresult_list is None:<EOL><INDENT>pfresult_list = [None for x in lclist]<EOL><DEDENT>for lc, pf in zip(lclist, pfresult_list):<EOL><INDENT>this_item = {<EOL>'<STR_LIT:target>': lc,<EOL>'<STR_LIT:action>': '<STR_LIT>',<EOL>'<STR_LIT:args>': (pf,),<EOL>'<STR_LIT>':runcp_kwargs if runcp_kwargs is not None else {},<EOL>'<STR_LIT>': result_bucket,<EOL>'<STR_LIT>': outq_url<EOL>}<EOL>resp = awsutils.sqs_put_item(inq_url, this_item, client=sqs_client)<EOL>if resp:<EOL><INDENT>LOGINFO('<STR_LIT>' % (lc,inq_url))<EOL><DEDENT><DEDENT>done_objects = {}<EOL>LOGINFO('<STR_LIT>')<EOL>signal.signal(signal.SIGINT, kill_handler)<EOL>signal.signal(signal.SIGTERM, kill_handler)<EOL>while len(list(done_objects.keys())) < len(lclist):<EOL><INDENT>try:<EOL><INDENT>result = awsutils.sqs_get_item(outq_url, client=sqs_client)<EOL>if result is not None and len(result) > <NUM_LIT:0>:<EOL><INDENT>recv = result[<NUM_LIT:0>]<EOL>try:<EOL><INDENT>processed_object = recv['<STR_LIT>']['<STR_LIT:target>']<EOL><DEDENT>except KeyError:<EOL><INDENT>LOGWARNING('<STR_LIT>' % recv)<EOL>processed_object = '<STR_LIT>'<EOL><DEDENT>cpf = recv['<STR_LIT>']['<STR_LIT>']<EOL>receipt = recv['<STR_LIT>']<EOL>if processed_object in lclist:<EOL><INDENT>if processed_object not in done_objects:<EOL><INDENT>done_objects[processed_object] = [cpf]<EOL><DEDENT>else:<EOL><INDENT>done_objects[processed_object].append(cpf)<EOL><DEDENT>LOGINFO('<STR_LIT>' % (processed_object, cpf))<EOL>if download_when_done:<EOL><INDENT>getobj = awsutils.awsutils.s3_get_url(<EOL>cpf,<EOL>client=s3_client<EOL>)<EOL>LOGINFO('<STR_LIT>' % (cpf, getobj))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>LOGWARNING('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL><DEDENT>awsutils.sqs_delete_item(outq_url, receipt)<EOL><DEDENT><DEDENT>except KeyboardInterrupt as e:<EOL><INDENT>LOGWARNING('<STR_LIT>')<EOL>break<EOL><DEDENT><DEDENT>LOGINFO('<STR_LIT>')<EOL>time.sleep(<NUM_LIT:1.0>)<EOL>if purge_queues_when_done:<EOL><INDENT>LOGWARNING('<STR_LIT>')<EOL>sqs_client.purge_queue(QueueUrl=inq_url)<EOL>sqs_client.purge_queue(QueueUrl=outq_url)<EOL>time.sleep(<NUM_LIT>)<EOL><DEDENT>if delete_queues_when_done:<EOL><INDENT>LOGWARNING('<STR_LIT>')<EOL>awsutils.sqs_delete_queue(inq_url)<EOL>awsutils.sqs_delete_queue(outq_url)<EOL><DEDENT>work_state = {<EOL>'<STR_LIT>': done_objects,<EOL>'<STR_LIT>': list(set(lclist) - set(done_objects.keys())),<EOL>'<STR_LIT:args>':((os.path.abspath(lightcurve_list) if<EOL>isinstance(lightcurve_list, str) else lightcurve_list),<EOL>input_queue,<EOL>input_bucket,<EOL>result_queue,<EOL>result_bucket),<EOL>'<STR_LIT>':{'<STR_LIT>':pfresult_list,<EOL>'<STR_LIT>':runcp_kwargs,<EOL>'<STR_LIT>':process_list_slice,<EOL>'<STR_LIT>':download_when_done,<EOL>'<STR_LIT>':purge_queues_when_done,<EOL>'<STR_LIT>':save_state_when_done,<EOL>'<STR_LIT>':delete_queues_when_done}<EOL>}<EOL>if save_state_when_done:<EOL><INDENT>with open('<STR_LIT>','<STR_LIT:wb>') as outfd:<EOL><INDENT>pickle.dump(work_state, outfd, pickle.HIGHEST_PROTOCOL)<EOL><DEDENT><DEDENT>return work_state<EOL>
This sends checkplot making tasks to the input queue and monitors the
    result queue for task completion.

    Parameters
    ----------

    lightcurve_list : str or list of str
        This is either a string pointing to a file containing a list of light
        curves filenames to process or the list itself. The names must
        correspond to the full filenames of files stored on S3, including all
        prefixes, but not include the 's3://<bucket name>/' bit (these will be
        added automatically).

    input_queue : str
        This is the name of the SQS queue which will receive processing tasks
        generated by this function. The queue URL will automatically be obtained
        from AWS.

    input_bucket : str
        The name of the S3 bucket containing the light curve files to process.

    result_queue : str
        This is the name of the SQS queue that this function will listen to for
        messages from the workers as they complete processing on their input
        elements. This function will attempt to match input sent to the
        `input_queue` with results coming into the `result_queue` so it knows
        how many objects have been successfully processed. If this function
        receives task results that aren't in its own input queue, it will
        acknowledge them so they complete successfully, but not download them
        automatically. This handles leftover tasks completing from a previous
        run of this function.

    result_bucket : str
        The name of the S3 bucket which will receive the results from the
        workers.

    pfresult_list : list of str or None
        This is a list of periodfinder result pickle S3 URLs associated with
        each light curve. If provided, this will be used to add in phased light
        curve plots to each checkplot pickle. If this is None, the worker loop
        will produce checkplot pickles that only contain object information,
        neighbor information, and unphased light curves.

    runcp_kwargs : dict
        This is a dict used to pass any extra keyword arguments to the
        `lcproc.checkplotgen.runcp` function that will be run by the worker
        loop.

    process_list_slice : list
        This is used to index into the input light curve list so a subset of the
        full list can be processed in this specific run of this function.

        Use None for a slice index elem to emulate single slice spec behavior:

        process_list_slice = [10, None]  -> lightcurve_list[10:]
        process_list_slice = [None, 500] -> lightcurve_list[:500]

    purge_queues_when_done : bool
        If this is True, and this function exits (either when all done, or when
        it is interrupted with a Ctrl+C), all outstanding elements in the
        input/output queues that have not yet been acknowledged by workers or by
        this function will be purged. This effectively cancels all outstanding
        work.

    delete_queues_when_done : bool
        If this is True, and this function exits (either when all done, or when
        it is interrupted with a Ctrl+C'), all outstanding work items will be
        purged from the input/queues and the queues themselves will be deleted.

    download_when_done : bool
        If this is True, the generated checkplot pickle for each input work item
        will be downloaded immediately to the current working directory when the
        worker functions report they're done with it.

    save_state_when_done : bool
        If this is True, will save the current state of the work item queue and
        the work items acknowledged as completed to a pickle in the current
        working directory. Call the `runcp_producer_loop_savedstate` function
        below to resume processing from this saved state later.

    s3_client : boto3.Client or None
        If None, this function will instantiate a new `boto3.Client` object to
        use in its S3 download operations. Alternatively, pass in an existing
        `boto3.Client` instance to re-use it here.

    sqs_client : boto3.Client or None
        If None, this function will instantiate a new `boto3.Client` object to
        use in its SQS operations. Alternatively, pass in an existing
        `boto3.Client` instance to re-use it here.

    Returns
    -------

    dict or str
        Returns the current work state as a dict or str path to the generated
        work state pickle depending on if `save_state_when_done` is True.