我正在尝试使用python asyncio取消运行事件循环中的任务

2024-06-06 09:14:30 发布

您现在位置:Python中文网/ 问答频道 /正文

嗨,我被问题难住了。我使用的是Python版本3.7.3。 对不起,我的英语不是以英语为母语的

我正在为《天才》写一篇歌词剧本

这是我的剧本。 如果我最终不能给出结果,每个请求都会被重复6次。 几乎在同一时间,我将get请求分了两次。意思是2*3

检查结果,如果我能得到结果,我想停止其他任务。 因为要少一些要求。 所以我用了cancel(),当我得到歌词时,我试着提高asyncio.exceptions.CancelledError,但效果不好。 它显示了RuntimeError: Event loop is closed我不知道为什么它不能很好地工作。 请教我一些熟悉这种情况的人

import asyncio
import requests
from bs4 import BeautifulSoup, Comment


#Lyrics__Container-sc-1ynbvzw-2

class Lyric():
    def __init__(self, artist, song_name):
        self.artist = artist
        self.song_name = song_name
        self.__gtask = []
        self.__canceled = False
        self.__lyric = ''

        
        self.genius_url = self.make_genius_url(artist, song_name)
        lyric = self.lyric_from_genius(self.genius_url)
        print(lyric)
    
    def make_genius_url(self, artist, song_name):
        search_song = f'{artist} {song_name}'
        search_song = search_song.replace(' ', '-')
        print(search_song)
        return f'https://genius.com/{search_song}-lyrics'
    

    def get_soup(self, url):
        r = requests.get(url)
        if r.status_code == 200:
            soup = BeautifulSoup(r.content, 'lxml')
            return soup
        else:
            return False
    
    def scrape_genius(self, url):
        soup = self.get_soup(url)
        if soup and not self.__canceled:
            lyric_soup = soup.select('.song_body-lyrics .lyrics p')
            if lyric_soup:
                self.__canceled = True
                tags = lyric_soup[0].find_all(['a', 'i'])
                for tag in tags:
                    tag.unwrap()
                print('ここから歌詞です。')
                print(lyric_soup[0].text)
                self.__lyric = lyric_soup[0].text
                self.__gtask.cancel()
            else:
                print('歌詞情報を取得出来なかった。')
        else:
            if self.__canceled:
                print('歌詞取得した')
            else:
                print('歌詞情報がない')
            self.__gtask.cancel()


    def lyric_from_genius(self, url):

        async def main_loop(url):
            sem = asyncio.Semaphore(2)
            async def get_lyric_soup(url):
                async with sem:
                    await self.loop.run_in_executor(None, self.scrape_genius, url)
            
            #main_loopの処理       
            for _ in range(6):
                self.__gtask += [get_lyric_soup(url)]
            return await asyncio.gather(*self.__gtask)
        
        try:
            self.loop = asyncio.new_event_loop()
            self.loop.run_until_complete(main_loop(url))
        except asyncio.exceptions.CancelledError as e:
            print("*** CancelledError ***", e)
        finally:
            if self.__lyric:
                return self.__lyric
            else:
                print('5回のリクエストで曲情報が取れなかった。')
        
        


Lyric = Lyric('kamal', 'blue')

Tags: nameselfloopasynciourlsearchgetsong