3

Try make my code more asynchronous and get this eror:

find = (await loop.run_until_complete(a.finddb()[0])) TypeError: 'coroutine' object is not subscriptable

from telethon import TelegramClient, events, Button, utils, sync
import pymongo
from pymongo import TEXT
import re
import logging
import asyncio

class Search(): # search in mongodb
    def __init__(self, search): # connect to mongoDB
        self.search = search
        self.myclient = pymongo.MongoClient(
            "mongodb+srv://:@cluster0.ye4cx.mongodb.net/info?retryWrites=true&w=majority&ssl=true&ssl_cert_reqs=CERT_NONE")
        self.mydb = self.myclient["info"]
        self.mycol = self.mydb["comics"]


    async def searchdb(self): # finds all comics by request
        self.mycol.create_index([('title', TEXT)], default_language='english')
        self.find = self.mycol.find({"$text": {"$search": self.search}})
        if self.find.count() == 0:
            return 0
        else:
            return (self.find)

    async def finddb(self): # search info for 1 comics
        self.mycol.create_index([('title', TEXT)], default_language='english')
        self.find = self.mycol.find({"title": self.search})
        return (self.find)

@bot.on(events.NewMessage(pattern=r'(?<=|).*(?=|)')) # command for find comics info
async def find(event):
    loop = asyncio.get_event_loop()
    a = Search(event.text.replace("|", ""))
    find = await loop.run_until_complete(a.finddb()[0])
    await event.respond(f'**|{find.get("title")}|**\n\n**Статус перевода**: {find.get("status")}\n**Издатель**: {find.get("publisher")}\n\n**Жанр**: {find.get("genres")}\n**Описание**:\n{find.get("description")}', buttons=[[Button.inline('Ссылки на скачку',  b'next')]])

I try to use motor, but have same problem, but why it doesn't work? With pymongo it work perfect

New trouble find = (await a.finddb())[0] TypeError: 'AsyncIOMotorCursor' object is not subscriptable

from telethon import TelegramClient, events, Button, utils, sync
import re
import logging
import motor.motor_asyncio

class Search(): # search in mongodb
    def __init__(self, search): # connect to mongoDB
        self.search = search
        self.myclient = motor.motor_asyncio.AsyncIOMotorClient("mongodb+srv://login:[email protected]/info?retryWrites=true&w=majority&ssl=true&ssl_cert_reqs=CERT_NONE")
        self.mydb = self.myclient["info"]
        self.mycol = self.mydb["comics"]



    async def searchdb(self): # finds all comics by request
        self.find = self.mycol.find({"$text": {"$search": self.search}})
        print(self.find)
        if self.find.count() == 0:
            return 0
        else:
            return (self.find)

    async def finddb(self): # search info for 1 comics
        self.find = self.mycol.find({"title": self.search})
        return (self.find)

@bot.on(events.NewMessage(pattern=r'(?<=|).*(?=|)')) # command for find comics info
async def find(event):
    a = Search(event.text.replace("|", ""))
    find = (await a.finddb())[0]
    print(find)
    await event.respond(f'**|{find.get("title")}|**\n\n**Статус перевода**: {find.get("status")}\n**Издатель**: {find.get("publisher")}\n\n**Жанр**: {find.get("genres")}\n**Описание**:\n{find.get("description")}', buttons=[[Button.inline('Ссылки на скачку',  b'next')]])
1
  • This says that a.finddb() returns a coroutine object, which isn't something you can treat like a list by asking for its first item. Commented Oct 19, 2020 at 15:51

1 Answer 1

6

First let's start with some general notes. find is defined as a coroutine.

async def finddb(self):

You need to await it in order to execute it.

db = await self.finddb()

You can then index into its return value.

db[0]

If you'd like to continue to do this all in one line, you'll need to wrap it in parentheses.

(await self.finddb())[0]

Now onto your actual code. find is also a coroutine. You can't start an event loop inside one. When you call loop.run_until_complete, you're going to get a RuntimeError because the loop is already running. You also can't await run_until_complete as it isn't a coroutine. (await and run_until_complete are both ways to run a coroutine or task. The former is used inside a coroutine; the latter is used outside one.)

You can reduce your code to

find = (await a.finddb())[0]

You can also further simplify it by using PyMongo's find_one rather than find if you only ever care about the first document it returns.

Lastly, PyMongo itself is not asyncio-aware. You are effectively writing synchronous code with the added overhead of an event loop. If you'd like to potentially benefit from asyncio, you should look at using Motor instead.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks you, now I understand my mistake
Can you please help me again, I change client to self.myclient = motor.motor_asyncio.AsyncIOMotorClient("mongodb+srv://login:[email protected]/info?retryWrites=true&w=majority&ssl=true&ssl_cert_reqs=CERT_NONE") and have error message = await event.get_message() TypeError: 'AsyncIOMotorCursor' object is not subscriptable or find = (await a.finddb())[0] TypeError: 'AsyncIOMotorCursor' object is not subscriptable
As I said above, you should use find_one instead of find.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.