【问题标题】:How I can avoid using "global" with asyncio (telethon)?如何避免将“全局”与 asyncio(电视节目)一起使用?
【发布时间】:2020-12-10 19:06:44
【问题描述】:

据我所知,在 python 中使用“全局”是一种不好的做法,但我不知道如何在这里避免它。 提前谢谢你。

import asyncio
from telethon import TelegramClient, sync, events

api_id = ***
api_hash = '***'

client = TelegramClient('session_name', api_id, api_hash).start()

channel_id = ***

@client.on(events.NewMessage(chats=channel_id))
async def handler(event):
    text = event.raw_text.lower()

    global task

    if text == 'start':
        task = client.loop.create_task(main())
        await client.send_message(channel_id, 'task was started')

    if text == 'stop':
        task.cancel()
        await client.send_message(channel_id, 'task was canceled')

async def main():
    while True:
        await client.send_message(channel_id, 'do something')
        await asyncio.sleep(3)

client.run_until_disconnected()

【问题讨论】:

  • 通常人们使用类变量而不是全局变量,并且只是传递对该类的引用。或者,您可以让该类包含所有变量 逻辑,因此您甚至不必传递引用。当然,前提是你应该防范竞态条件和其他线程陷阱,如果它是全局的,你就必须这样做。

标签: python python-asyncio telethon


【解决方案1】:

查看文档,我找不到将客户端与类一起使用的推荐方法,但您应该始终能够自己连接它。例如:

class MyClient:
    def __init__(self, client):
        self.task = None
        self.client = client

    async def on_message(self, channel_id, event):
        text = event.raw_text.lower()

        if text == 'start':
            self.task = self.client.loop.create_task(self.main(channel_id))
            await self.client.send_message(channel_id, 'task was started')

        if text == 'stop':
            self.task.cancel()
            await self.client.send_message(channel_id, 'task was canceled')

    async def main(self, channel_id):
        while True:
            await self.client.send_message(channel_id, 'do something')
            await asyncio.sleep(3)

def run_client():
    # instantiate telegram client, my client, and connect the two
    api_id = ***
    api_hash = '***'

    channel_id = ***

    client = TelegramClient('session_name', api_id, api_hash).start()
    my_client = MyClient(client)

    @client.on(events.NewMessage(chats=channel_id))
    async def handle(event):
        await my_client.on_message(channel_id, event)

    client.run_until_disconnected()

run_client()

【讨论】:

  • 感谢您的提示,但我遇到了一些错误。我们必须将“client”和“channel_id”(如果我将它放在 def run_client() 中)传递给类。你能编辑你的代码吗? (对不起,琐碎的问题,我是初学者)
  • @ExKaSeT 我现在更新了代码,将client 包含在构造函数中。我还让它将channel_id 发送到on_message 而不是MyClient 的构造函数,这样您就可以在同一个客户端中拥有不同的channel_id。如果这对您的情况没有意义,因为您只有一个 channel_id,您可以轻松更改代码以将 channel_id 也发送到构造函数。
  • @ExKaSeT 我现在注意到main() 还需要clientchannel_id,所以我将它作为MyClient 上的一个方法,以便它可以访问该类的其他部分根据需要。
  • 谢谢,我做了一些修改,一切正常!不使用全局(可能是特殊的异步函数)没有更简单的方法吗?
  • @Lonami 也许您可以编写一个答案,根据您的建议调整我的答案中的代码。对于该网站的未来访问者来说,这将是一个很好的资源,因为从文档中它并不完全显而易见。最初可能只是便利功能的意思现在被视为功能的主要接口。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
相关资源
最近更新 更多