返回

Telegram Bot TypeError: 'function'不可迭代 - 解决方法

python

Telegram Bot 报错:TypeError:参数类型“function”不可迭代

在开发 Telegram 机器人时,使用 telebot 库时可能会遇到一种常见错误: TypeError: argument of type 'function' is not iterable。这个错误通常在尝试设置消息处理器时出现,尤其在使用 commands 参数时。这种类型错误通常说明,代码将函数作为 commands 列表中的一个元素传递了。

问题分析

错误信息清楚地表明 commands 参数期望接收一个字符串列表(commands),而非一个函数。在 telebot 中,@bot.message_handler(commands=...) 装饰器用来处理以特定命令开头的消息。如果把函数传递给这个参数,telebot 就无法对消息进行解析,导致“不可迭代”的 TypeError。错误堆栈追踪表明问题出现在message_handler内部的命令过滤器部分。这通常是因为将函数传递给了参数 commands,该参数必须为字符串列表,以便筛选 Telegram 消息的指令。错误的原因并非 show_help 本身的问题。错误真正出现是因为当在命令列表(即函数参数)里发现它不是字符串而是一个函数时候抛出的。

代码示例中的问题

提供的示例中,可以看到, @bot.message_handler 被用于处理不同类型的消息:

  • /start 命令:
 @bot.message_handler(commands=['start'])
def send_welcome(message):
     # ...代码...
 ```
 这个处理器通过 commands 参数来接收,这是正常的。

*   文本按钮的点击, 例如 "💰 Баланс"
 ```python
@bot.message_handler(func=lambda message: message.text == '💰 Баланс')
 def show_balance(message):
     # ...代码...
 ```
这个处理器使用一个匿名函数过滤消息,同样没有问题。

*  但是,如果按照将 @bot.message_handler的func参数删除就会抛出错误
```python
@bot.message_handler(lambda message: message.text == '❓ Помощь')
 def show_help(message):
   # ...代码...
这段代码中,应该传递一个 commands 参数字符串列表,但实际上接收到一个 `func` 函数或者匿名函数作为过滤器参数,这就是错误的关键。错误的原因在于开发者对  `message_handler` 使用方法理解不足造成的。

解决方案

这个错误需要通过明确 message_handler 中的命令过滤器参数来实现。正确的做法包括:

  1. 使用 commands 参数来处理以特定命令开头的信息: 使用一个字符串列表来表示期望的指令。 例如: /start, /help 等。
  2. 使用 func 参数搭配lambda匿名函数过滤其他文本消息:
    对于不以指令开始,只是纯文本信息,需要利用func进行过滤。 lambda 表达式提供了一个轻量的方法定义这个过滤器。
  3. 如果一个函数抛出了 TypeError, 不代表这个函数有问题。 需要根据错误提示溯源,寻找产生错误的实际原因,对症下药。

解决方案一: 使用 commands 参数 (处理 /start 类似命令)

当需要通过命令触发时,需在装饰器 bot.message_handler 中指定 commands 参数。

  • 代码示例:

    import telebot
    from telebot import types
    
    bot = telebot.TeleBot("YOUR_TELEGRAM_BOT_TOKEN") # 替换成你的 Telegram Bot Token
    
    @bot.message_handler(commands=['start', 'help'])
    def handle_commands(message):
        if message.text == '/start':
             #  ...处理 /start ...
              bot.reply_to(message, "Welcome")
        elif message.text == '/help':
            # ...处理 /help...
             bot.reply_to(message, "This is the help message")
    
    @bot.message_handler(func=lambda message: message.text == '💰 Баланс')
    def show_balance(message):
       #  ...处理balance点击事件...
          bot.reply_to(message, "Balance 20")
    
    @bot.message_handler(func=lambda message: message.text == '❓ Помощь')
    def show_help(message):
        #  ...处理help点击事件...
           bot.reply_to(message, "Help Text Here")
    
    
    bot.polling()
    
    
    • 操作步骤:
      1. 将你的 bot token 替换示例中的 "YOUR_TELEGRAM_BOT_TOKEN"
      2. 在终端或命令行窗口中,运行脚本。
      3. 在 Telegram 中向你的机器人发送 /start/help 命令或点击 '💰 Баланс' 和'❓ Помощь' 按钮,机器人应该响应你设置的消息。

    安全性提示

    • 务必保护你的 bot token ,不要将其公开到公开仓库或未加密的代码中。

解决方案二: 使用 func 参数过滤普通文本消息(处理键盘点击事件)

如果仅仅想根据文本匹配过滤信息, 需要使用 func 参数配合lambda表达式实现消息过滤,过滤不需要指令头的消息,类似按钮点击。

  • 代码示例:

import telebot
from telebot import types

bot = telebot.TeleBot("YOUR_TELEGRAM_BOT_TOKEN") # 替换成你的 Telegram Bot Token

@bot.message_handler(commands=['start'])
def send_welcome(message):
# ...回复开始信息并且初始化键盘...
markup = types.ReplyKeyboardMarkup(row_width=2)
buttons = [
'💰 Баланс',
'📊 Торговля',
'📈 Курсы',
'📝 Мои ордера',
'💳 Пополнить',
'💸 Вывести',
'⚙️ Настройки',
'❓ Помощь'
]
markup.add(*[types.KeyboardButton(button) for button in buttons])

bot.reply_to(message, 
            "Добро пожаловать", 
            reply_markup=markup)

@bot.message_handler(func=lambda message: message.text == '💰 Баланс')
def show_balance(message):
# ...回复余额信息...
response = "💰 Ваш баланс: 20"
bot.reply_to(message, response)

@bot.message_handler(func=lambda message: message.text == '❓ Помощь')
def show_help(message):
# ...回复帮助信息...
help_text = "0"
bot.reply_to(message, help_text)

bot.polling()

    
    *  **操作步骤:** 
    1.  将你的 bot token 替换示例中的 `"YOUR_TELEGRAM_BOT_TOKEN"`
    2. 在终端或命令行窗口中,运行脚本。
    3. 在 Telegram 中向你的机器人发送 `/start` ,然后点击按钮。

### 代码风格

以上解决方案示例展示了一种整洁和模块化的风格,推荐根据这个进行开发。这样组织的代码逻辑更清晰,维护更容易。使用长短句结合的方式,使内容阅读更轻松。

## 总结

`TypeError: argument of type 'function' is not iterable` 错误通常是因为在 `bot.message_handler` 中错误地使用了函数。正确的做法是在 `commands` 中指定命令列表,在 `func` 中使用 lambda 表达式定义过滤逻辑,从而确保代码能够按照预期正确工作。遵循以上的方案能够有效解决遇到的问题,让你的 Telegram 机器人开发工作更顺畅。