python-telegram-bot / python-telegram-bot

We have made you a wrapper you can't refuse
https://python-telegram-bot.org
GNU General Public License v3.0
26.43k stars 5.36k forks source link

[BUG]PRE Version not support run_polling in thread #3371

Closed pofey closed 2 years ago

pofey commented 2 years ago

Steps to Reproduce

  1. read doc from https://docs.python-telegram-bot.org/en/v20.0a4/examples.webappbot.html
  2. create start function and create new_event_loop in thread target function
  3. start thread,raise exception "ValueError: set_wakeup_fd only works in main thread of the main interpreter"

Expected behaviour

can be run in python thread

Actual behaviour

raise exception "ValueError: set_wakeup_fd only works in main thread of the main interpreter"

Operating System

macos python3.9

Version of Python, python-telegram-bot & dependencies

pip install python-telegram-bot==20.0a4

Relevant log output

Exception in thread Thread-9:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/unix_events.py", line 95, in add_signal_handler
    signal.set_wakeup_fd(self._csock.fileno())
ValueError: set_wakeup_fd only works in main thread of the main interpreter

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/yee/workspace/python/movie-bot/plugins/tgbot-ptb/tgbot.py", line 180, in start_bot
    application.run_polling()
  File "/Users/yee/workspace/python/movie-bot/venv/lib/python3.9/site-packages/telegram/ext/_application.py", line 648, in run_polling
    return self.__run(
  File "/Users/yee/workspace/python/movie-bot/venv/lib/python3.9/site-packages/telegram/ext/_application.py", line 803, in __run
    loop.add_signal_handler(sig, self._raise_system_exit)
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/unix_events.py", line 97, in add_signal_handler
    raise RuntimeError(str(exc))
RuntimeError: set_wakeup_fd only works in main thread of the main interpreter

Additional Context

def start_bot(config: Dict) -> None:
    loop = asyncio.new_event_loop()
    try:
        asyncio.set_event_loop(loop)
        """Run the bot."""
        application = Application.builder().token("xxxxx").build()
        application.add_handler(CommandHandler("rebootmr", rebootmr))
        application.add_handler(CommandHandler("help", help_command))
        application.add_handler(CallbackQueryHandler(button))
        application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, echo1))
        application.run_polling()
    finally:
        loop.close()
        pass

@plugin.after_setup
def main(plugin: PluginMeta, config: Dict):
    thread = threading.Thread(target=start_bot, args=(config,))
    thread.start()
Bibo-Joshi commented 2 years ago

Hi, thanks for reaching out.

We could indeed make a broader except clause here:

https://github.com/python-telegram-bot/python-telegram-bot/blob/2642ecc7379907a72dc5ef68791b30b18c18c1d2/telegram/ext/_application.py#L800-L810

to avoid this issue. As a workaround, you can explicitly pass stop_signals=None to prevent PTB from setting the signal handlers.

That said, you are miking threading with asyncio, which is rarely advisable. PTB v20 is designed to play well with other asyncio setups, so you might want to consider doing that instead :)

btw, run_polling will by default close the event loop on exit anyway, unless you set close_loop=False - so you can probably skip the loop.close() in the finally clause.

pofey commented 2 years ago

Thank you for your response, the issue has been resolved