Thinking in Python

November 12, 2023

I’ve just finished my first diving into a new language for me, Python. After having a short break I will probably dive again, now with hosting of the solution in my home Raspberry Pi. Or probably not short, just because I have lots of other things to do. Right now I want to sum up my first impressions and feelings about it.

Let’s start from the end. The source code is available at https://github.com/XCoReD/TennisBotY. As you may see, it is a bot, and it is about tennis. Particularly, the idea was to automate several tasks that regularly arise in a small community of Table Tennis lovers I know in person:

  1. Automate the registration of participants to a new training event. The facility we play in has a limited set of tables, and it is important that the number of players does not exceed the maximum amount.
  2. Make sure all the newcomers agree with the rules of the community, and get some background info about them.

Technically, I expected from the bot also that she should monitor messages from users and allow them to interact in a more human-friendly way, with no saying “/start” at the beginning if possible. My fantasy also added some advanced antibot-checking, when my bot would ask new users about some facts about their table tennis experience, and then check if their answers were relevant to questions asked by means of ChatGPT or other LLM. I checked how it would work, and found that ChatGPT knows what table tennis is and can talk about it quite well, but decided to postpone this “feature set” because wanted to stay on the free tier if possible and concentrate on the core functions first. Also, another feature, private conversation with users in their languages, remained postponed too.

The most challenging task for me as a developer of this pet project was to change the paradigm of development. Python mildly points you to the only one proper way, when you first write the unit test code, then write your source code. Otherwise, you can spend tons of effort to stabilize the application. The linter is the essential part too, you can treat it as a replacement for strict compile-time type checking.

What I found a bit complicated:

  1. For unit testing of the chatbot written with python-telegram-bot, I decided to use another library, telethon. It was not quite trivial for me to send a message by telethon and then make sure that the telegram bot processed it, and then the telethon processed a reply from the bot.
  2. Even having my own dedicated test chat with just 3 contacts, and sending the messages with delays, did not prevent me from being banned by Telegram for flood. Telethon handles small delays, requested by Telegram flood prevention, but with larger ones, it requires explicit handling. Thus, running a dedicated server for simulating the Telegram server makes sense.
  3. The function below returned the seemingly right value, but the variable outside the function did not get it until I added this declaration.

I feel the ugliness of the 100th level at this code:

Or this one:

However, this code seems to me quite good:

My remaining TODO list items with Python and this project are:

  1. Read an “Effective Python” book, and rewrite the ugly code shown above.
  2. Launch the bot in my Raspberry PI box.
  3. Add comments to the source code, so not only I can understand it 🙂