I keep getting an error in the following code
INFO:userbot:Starting userbot Ynjxsjmh
<coroutine object AuthMethods._start at 0x7fde36d996d0>
Traceback (most recent call last):
File "userbot.py", line 58, in <module>
asyncio.get_event_loop().run_until_complete(main())
File "/home/winy/.pyenv/versions/3.6.8/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete
return future.result()
File "userbot.py", line 53, in main
await bot.send_message_to_friends()
File "userbot.py", line 47, in send_message_to_friends
for friend in friends
File "userbot.py", line 47, in <listcomp>
for friend in friends
AttributeError: 'coroutine' object has no attribute 'send_message'
sys:1: RuntimeWarning: coroutine 'AuthMethods._start' was never awaited
import asyncio
import logging
import json
import sys
from configparser import ConfigParser
from os import listdir, path
from telethon import TelegramClient
class UserBot:
"""telegram user bot class."""
def __init__(self):
"""init the userbot."""
self.logger = logging.getLogger("userbot")
config = ConfigParser()
config.read(path.join(path.dirname(__file__), "config.ini"))
for configsection in config:
if ("api_id" in config[configsection] and
"api_hash" in config[configsection]):
self.api_id = config[configsection]["api_id"]
self.api_hash = config[configsection]["api_hash"]
self.name = configsection
else:
self.logger.warning(f"Invalid configration in {configsection}")
try:
client = TelegramClient(self.name, self.api_id, self.api_hash)
except (NameError, AttributeError):
raise ValueError("Invalid configration: need api_id and api_hash")
self.logger.info(f"Starting userbot {self.name}")
self.userbot = client.start()
print(self.userbot)
print(client.start())
async def send_message_to_friends(self):
friends = [
'@friend1__username',
]
# wait for all client.send_message to complete
await asyncio.wait([
self.userbot.send_message(friend, 'test')
for friend in friends
])
async def main():
bot = UserBot()
await bot.send_message_to_friends()
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
However, the example I'm following doesn't give the error.
An example from An Introduction to Asyncio gives the following code:
# we will have to await things, so we need an async def
async def main(message):
# start is a coroutine, so we need to await it to run it
client = await TelegramClient('me', api_id, api_hash).start()
# wait for all three client.send_message to complete
await asyncio.wait([
client.send_message(friend, message)
for friend in friends
])
# and close our client
await client.disconnect()
It says start is a coroutine, so we need to await it to run it. So I think the problem in my code is that I don't await start at self.userbot = client.start().
My question is why the emacs-china-bot doesn't await start but still works. How can I modify my code to make it work except using importlib.util like what emacs-china-bot does.
I also see an example from Telethon Documentation
In this example, it uses with..as.. syntax rather than await start, how does this work?
I edit my code like what the poster in How to set class attribute with await in __init__ does:
import asyncio
import logging
import json
import sys
from configparser import ConfigParser
from os import listdir, path
from telethon import TelegramClient
class UserBot:
"""telegram user bot class."""
def __init__(self):
"""init the userbot."""
self.logger = logging.getLogger("userbot")
config = ConfigParser()
config.read(path.join(path.dirname(__file__), "config.ini"))
for configsection in config:
if ("api_id" in config[configsection] and
"api_hash" in config[configsection]):
self.api_id = config[configsection]["api_id"]
self.api_hash = config[configsection]["api_hash"]
self.name = configsection
else:
self.logger.warning(f"Invalid configration in {configsection}")
try:
self.client = TelegramClient(self.name, self.api_id, self.api_hash)
except (NameError, AttributeError):
raise ValueError("Invalid configration: need api_id and api_hash")
async def async_init(self):
self.logger.info(f"Starting userbot {self.name}")
self.userbot = await self.client.start()
async def send_message_to_friends(self):
friends = [
'@friend1__username',
]
# wait for all client.send_message to complete
await asyncio.wait([
self.userbot.send_message(friend, 'test')
for friend in friends
])
async def main():
bot = UserBot()
await bot.async_init()
await bot.send_message_to_friends()
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.get_event_loop().run_until_complete(main())
This question is still looking for answers why the emacs-china-bot doesn't await start but still works.