pythonpython-3.xlistoperandsloguru

Python error with literals and lists in loguru: unsupported operand type(s) for +: 'NoneType' and 'list'


Working with loguru in order to write a list back to the configuration file, and received the dreaded unsupported operand type(s) for +: 'NoneType' and 'list' error. I know the error came from attempting to combine a literal and a list. I attempted to break down the line by using a variable to represent the literal, and this only generated the same error.

Block of code with problematic line:

def update_config(config: dict):
    """
    Update exisitng configuration file.

    Parameters
    ----------
    config: dict
        Configuraiton to be written into config file.
    """
    config["ids_to_retry"] = list(set(config["ids_to_retry"] + FAILED_IDS))
    with open("config.yaml", "w") as yaml_file:
        yaml.dump(config, yaml_file, default_flow_style=False)
    logger.info("Updated last read message_id to config file")

Full error output:

Traceback (most recent call last):                                                                                                                             
  File "/telegram-downloader-quackified/media_downloader.py", line 359, in <module>                                                               
    main()                                                                                                                                                     
  File "/telegram-downloader-quackified/media_downloader.py", line 343, in main                                                                   
    updated_config = asyncio.get_event_loop().run_until_complete(                                                                                              
  File "/miniconda3/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete                                                                
    return future.result()                                                                                                                                     
  File "/telegram-downloader-quackified/media_downloader.py", line 324, in begin_import                                                           
    update_config(config)                                                                                                                                      
  File "/telegram-downloader-quackified/media_downloader.py", line 35, in update_config                                                           
    config["ids_to_retry"] = list(set(config["ids_to_retry"] + FAILED_IDS))

I know something needs to change in the phrase list(set(config["ids_to_retry"] + FAILED_IDS)), I just am not sure what.


Providing more info:

FAILED_IDS is a list generated when the script encounters an exception and cannot successfully complete the download. When this occurs the message id is stored in memory like so FAILED_IDS.append(message.message_id). Then it is written to the configuration file with the following statement:

if FAILED_IDS:
        logger.info(
            "Downloading of %d files failed. "
            "Failed message ids are added to config file.\n",
            len(set(FAILED_IDS)),
        )
    update_config(updated_config)

It's original value is:

FAILED_IDS: list = []

Where "ids_to_retry" is more or less just a label used in the configuration file. It is just a literal string, and is the nonetype. The ends result is for the two to be written in the configuration file to resemble something like the following:

ids_to_retry:
- 26125
- 2063
- 2065
- 2080
- 2081
- 22052
- 21029
- 553
- 554
- 555
- 2102
- 22074

I hope this clarifies the nature of the variables we are working with.


Solution

  • The reason for failure is config["ids_to_retry"] = None and you are trying to extend a Nonetype to a list. You can use something like

    config["ids_to_retry"] = list(set(config["ids_to_retry"] + FAILED_IDS)) if config["ids_to_retry"] else FAILED_IDS

    So if config["ids_to_retry"] is None it would take config["ids_to_retry"] = FAILED_IDS, Without trying to extending it.

    Assumption made that FAILED_IDS is a list if not you can type cast it to a list.