0

I'm developing telegram bot on python (3.7). I'm getting POST updates/messages from users (class telegram.update.Update)

if request.method == "POST": 
    update = Update.de_json(request.get_json(force=True), bot)

Then I'm storing all the parameters of the incoming "message" in variables. For example, if there is a user status update, I save it this way:

if update and update.my_chat_member and update.my_chat_member.new_chat_member \
                and update.my_chat_member.new_chat_member.status:
    new_status = update.my_chat_member.new_chat_member.status
else:
    new_status = None

It's important to me to save 'None' if this parameter is not provided.

And I need to save about 20 parameters of this "message". Repeating this construction for 20 times for each parameter seems to be inefficient.

I tried to create a checking function to reuse it and to check if parameters exist in one line for each parameter:

def check(f_input):
    try:
        f_output = f_input
    except: # i understand it's too broad exception but as I learned it's fine for such cases
        f_output = None
    return f_output

new_status = check(update.my_chat_member.new_chat_member.status)

but , if a certain Update doesn't have update.my_chat_member, the error pops up already on the stage of calling the 'check' function

new_status = check(update.my_chat_member.new_chat_member.status)
>>> 'NoneType' object has no attribute 'new_chat_member'

and not inside the check().

Could someone guide me pls, if there is an intelligent way to save these 20 parameters (or save None), when the set of these parameters changes from message to message?

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Mike
  • 1
  • 1
  • what error? And what is your check fn supposed to do? It will always just return its input. – 2e0byo Dec 31 '21 at 11:30
  • 1
    Is there any reason in your long example not just to check `update.my_chat_member.new_chat_member.status`? Regardless, the logic in your 'check fn' is very different from the logic in your non-functional variant. And the check fn doesn't do what your think it does: it is equivalent to `def check(x): return x`. – 2e0byo Dec 31 '21 at 11:34
  • so, generally speaking, i don't know what will be the structure of the every simple Update i'm receiving, but I have 20 possible cases (of different incoming Update structures), which i'd like to catch and record important parameters for each of cases. I can record it with the try/except clauses for every parameter (in my example - for new_status), but seems it's not a pythonic way to repeat this try/except construction for 20 time in a code. – Mike Dec 31 '21 at 12:59
  • hanks @2e0byo, probably i was not very exact, sorry: messages, i'm receiving are different from one to another. If one message can have update.my_chat_member.new_chat_member.status another one can have no update.my_chat_member even – that's why in non-functional variant i use step-by-step verification if every "layer" of metods exist. If i use simply if update.my_chat_member.new_chat_member.status if will give me an error for cases when this "parameters brach" does not exist for specific message. The error is 'NoneType' object has no attribute 'new_chat_member' – Mike Dec 31 '21 at 13:21
  • 1
    What you want is called "optional chaining" in many languages which have it. Searching for that phrase turns up this: https://stackoverflow.com/questions/64285182/optional-chaining-in-python – Ture Pålsson Dec 31 '21 at 16:34
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Diego Ramirez Jan 08 '22 at 19:35

1 Answers1

0

You're trying to invoke methods on a NoneType object before passing it to your check function. The update.my_chat_member object itself is NoneType and has no new_chat_member method. A way to check that could look like this.

if not isinstance(update.my_chat_member, type(None)):
    *do what you need to a valid response*
else:
    *do what you need to a NoneType response*

Also as @2e0byo noted the check function doesn't really do much. You're checking to see if you can assign a variable to "f_output" which outside of a few cases will always pass without exception. So the except part will almost never run and certainly not as intended. You need to try something that can cause an expected error. This is an example using your code.

def check(f_input):
    try:
        f_output = f_input.new_chat_member.status()
    except AttributeError:
        f_output = None
    
    return f_ouput

new_status = check(update.my_chat_member)
BeanBagTheCat
  • 435
  • 4
  • 7