【问题标题】:Python slow for-loop in async func异步函数中的Python慢​​for循环
【发布时间】:2018-09-24 12:59:00
【问题描述】:

我正在尝试将Song-Objects 与我的Queue-Object 联系起来,以获取我从库Pafy 循环遍历Playlist-Object 的实际歌曲。

playlist = pafy.get_playlist("playlist url here")
counter = 0
for s in playlist["items"]:
    counter += 1
    s = s["pafy"]
    song = Song.Song(s.watchv_url, msg.author.name, s.title, s.description, s.author, s.published, s.duration,
                     s.likes, s.dislikes,
                     s.viewcount, s.thumb)
    if queue.add_song(song=song):
        print("Song " + str(counter) + " finished")
    else:
        print("Song " + str(counter) + " not added")

class Song:
    def __init__(self, url, requested_by, title, description, uploader, upload_date, duration, likes, dislikes, views, thumbnail):
        self.url = url
        self.requested_by = requested_by
        self.title = title
        self.description = description
        self.uploader = uploader
        self.upload_date = upload_date
        self.duration = duration
        self.likes = likes
        self.dislikes = dislikes
        self.views = views
        self.thumbnail = thumbnail

class PlayerQueue:
    list_of_songs = []
    length = 0
    current_song = []
    replaying = False
    random = False

    def add_song(self, song):
        try:
            self.length += 1
            self.list_of_songs.append(song)
            return True
        except Exception:
            return False

    def remove_song(self, song):
        if song in self.list_of_songs:
            self.length -= 1
            self.list_of_songs.remove(song)
            return True
        else:
            return False

    def replay(self):
        self.replaying = True

    def randomize(self):
        self.random = True

    def clear(self):
        self.list_of_songs = []
        self.length = 0
        self.replaying = False
        self.random = False

我也应该让add_song-Method 异步吗?

此代码循环一次大约需要 1-2 秒。 这让我遇到了asyncio 的问题,因为它会抛出TimeoutError。此错误在 30 秒后发生,对于 70 首歌曲,循环需要超过一分钟。这个循环这么慢吗,因为它在async def function 中运行?我什至可以让它更快吗?

这是错误:

    ERROR:asyncio:Task exception was never retrieved
    future: <Task finished coro=<VoiceClient.poll_voice_ws() done, defined 
    at C:\Users\user\AppData\Local\Programs\Python\Python35-32\lib\site-packages\discord\voice_client.py:269> exception=TimeoutError()>
    Traceback (most recent call last):
      File "C:\Users\user\AppData\Local\Programs\Python\Python35-32\lib\asyncio\tasks.py", line 239, in _step
        result = coro.send(None)
      File "C:\Users\user\AppData\Local\Programs\Python\Python35-32\lib\site-packages\discord\voice_client.py", line 276, in poll_voice_ws
        yield from self.ws.poll_event()
      File "C:\Users\user\AppData\Local\Programs\Python\Python35-32\lib\site-packages\discord\gateway.py", line 676, in poll_event
        msg = yield from asyncio.wait_for(self.recv(), timeout=30.0, loop=self.loop)
      File "C:\Users\user\AppData\Local\Programs\Python\Python35-32\lib\asyncio\tasks.py", line 396, in wait_for
        raise futures.TimeoutError()
    concurrent.futures._base.TimeoutError

我可以在现有的 asyncio.event.loop 中为我的 for 循环创建一个新任务,这样我就不会遇到这个 TimeoutError 吗?我应该试着抓住它然后继续吗?

Full code here

当前运行于:

英特尔 I5 系列 CPU

64 GB DDR4 内存

Python 3.x

【问题讨论】:

  • 你究竟是如何创建异步任务的? Song类和add_song队列方法从何而来?
  • 我在获得命令输入并在async def get_playlist_ready() 中正常调用它后创建任务。 myBot
  • 会不会是get_playlist 本身需要很长时间才能完成? playlist["items"] 列表有多大?
  • 在我的测试用例中,我使用了一个包含 76 首歌曲的播放列表。当我对我进行调试时,它看起来不需要那么长时间。所以playlist["items"]里面有76个对象。
  • 对于 70 首歌曲,循环需要超过一分钟您是否尝试过衡量这一分钟花费在哪里?看看循环,很难想象它需要一分钟来执行。

标签: python for-loop python-asyncio discord pafy


【解决方案1】:

我现在正在使用另一个库来下载播放列表。我正在使用 thread library 单独运行它,所以在加入 vc 之前,我在单独的线程中开始下载,所以我没有得到 timeout error

【讨论】:

    猜你喜欢
    • 2014-07-09
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    相关资源
    最近更新 更多