Pygithub: github.GithubException.RateLimitExceededException

Criado em 7 mai. 2019  ·  15Comentários  ·  Fonte: PyGithub/PyGithub

Estou tentando obter o número de problemas abertos usando o código a seguir em meu aplicativo Flask.

g = Github()

repo = g.get_repo(repo_name)

open_pulls = repo.get_pulls(state='open')
open_pull_titles = [pull.title for pull in open_pulls]

open_issues = repo.get_issues(state='open')
open_issues = [issue for issue in open_issues if issue.title not in open_pull_titles]

e recebo o erro github.GithubException.RateLimitExceededException: .

repo.get_issues() retorna a contagem de ocorrências abertas mais solicitações pull.

stale

Comentários muito úteis

Se bem entendi, o tipo de retorno de get_issues e get_pulls é PaginatedList. Ele usa yield element para iteração. Portanto, a solicitação não é realizada até open_issues = [issue for issue in open_issues if issue.title not in open_pull_titles] . Se seus limites de token forem atingidos, ele lançará a RateLimitExceedException.

Todos 15 comentários

Se bem entendi, o tipo de retorno de get_issues e get_pulls é PaginatedList. Ele usa yield element para iteração. Portanto, a solicitação não é realizada até open_issues = [issue for issue in open_issues if issue.title not in open_pull_titles] . Se seus limites de token forem atingidos, ele lançará a RateLimitExceedException.

Existe alguma solução alternativa?

g = Github()
Você autenticou nesta etapa? API pública tem menos limites de taxa.

g = Github()
Você autenticou nesta etapa? API pública tem menos limites de taxa.

Sim, autentiquei essa etapa.

@ 242jainabhi
O que normalmente faço quando alcanço o limite de taxa é apenas adiar o programa por algum tempo.

Em vez de usar a compreensão de lista, posso usar apenas um loop comum com try-catch. Assim que uma exceção de limite de taxa for detectada, chame a função sleep para esperar um pouco e verifique o limite de taxa com a API do GitHub novamente. O código só continua se o limite da taxa voltar a 5000.

Lamento por perder uma parte do código. Abaixo está o código na continuação do código no primeiro comentário.
Estou acessando created_at date para todas as edições em aberto. Isso acessará novamente a API para todos os problemas e, portanto, acabará fazendo chamadas além do limite.

for issue in open_issues:
    created_at = issue.created_at.timestamp()

Não consegui encontrar uma solução para este problema. Mesmo se eu autenticar as solicitações, o limite será esgotado se os problemas forem muitos (digamos 2000).

Algo assim:

repositories = g.search_repositories(
    query='stars:>=10 fork:true language:python')

Também aciona o limite da taxa. Presumo que esteja fazendo a paginação automaticamente e isso está acionando o limite de taxa? Existe alguma maneira de fazer manualmente para que eu possa pausar?

Agora percebo que este é um problema real.
Uma possível solução alternativa poderia ser um trecho de código como o abaixo. Ainda não experimentei, diga-me se funciona ou não.

iter_obj=iter(open_issues) ## PaginatedList is a generator
 while True:
    try:   
        issue=next(iter_obj) 
        ## do something
    except StopIteration:
        break  # loop end
    except github.GithubException.RateLimitExceededException:
        sleep(3600) # sleep 1 hour
        ## check token limits
        continue

@ wangpeipei90 Não funciona.

Por alguma razão, esse comportamento é altamente imprevisível e enlouquecedor.
Meu programa pode fazer um ciclo com eficácia e chamar preventivamente a API ratelimit para verificar se ela está de acordo com os limites de uma a duas horas antes de fornecer um 403 aleatoriamente.

Alguma adesão ao limite de taxa nativa seria uma recepção calorosa aqui. Ter que implementar o sleeps com base na intuição quando seu aplicativo decidir se livrar do problema após duas horas de execução suave não deve ser um comportamento esperado.

 File "word.py", line 126, in get_stargazers_inner
    for i in repo.get_stargazers_with_dates():
  File "/usr/local/lib/python3.6/dist-packages/github/PaginatedList.py", line 62, in __iter__
    newElements = self._grow()
  File "/usr/local/lib/python3.6/dist-packages/github/PaginatedList.py", line 74, in _grow
    newElements = self._fetchNextPage()
  File "/usr/local/lib/python3.6/dist-packages/github/PaginatedList.py", line 199, in _fetchNextPage
    headers=self.__headers
  File "/usr/local/lib/python3.6/dist-packages/github/Requester.py", line 276, in requestJsonAndCheck
    return self.__check(*self.requestJson(verb, url, parameters, headers, input, self.__customConnection(url)))
  File "/usr/local/lib/python3.6/dist-packages/github/Requester.py", line 287, in __check
    raise self.__createException(status, responseHeaders, output)
github.GithubException.RateLimitExceededException: 403 {'message': 'API rate limit exceeded for user ID xxxx.', 'documentation_url': 'https://developer.github.com/v3/#rate-limiting'}

Além disso, pode-se usar a biblioteca de backoff - no entanto, ela não pode levar em conta a posição atual na iteração do item e, portanto, começará do zero novamente.

Bem, eu visitei https://github.com/settings/tokens e fiz um "token regenerado". Isso me fez rolar de novo, mas não tenho certeza por quanto tempo.

Usei o método de autenticação "token". Exemplo:

    github = Github("19exxxxxxxxxxxxxxxxxxxxxe3ab065edae6470")

Veja também # 1233 para solicitações excessivas.

Este problema foi marcado automaticamente como obsoleto porque não teve atividades recentes. Ele será fechado se nenhuma outra atividade ocorrer. Obrigado por suas contribuições.

@ wangpeipei90

Funciona comigo, mas RateLimitExceededException não está abaixo de GithubException na versão que usei. Aqui está meu código.

from github import RateLimitExceededException

issues = g.search_issues(query=keyword, **{'repo': repo, 'type': 'pr'})
            iter_obj = iter(issues)
            while True:
                try:
                    pr = next(iter_obj)
                    with open(pr_file, 'a+') as f:
                        f.write(pr.html_url + '\n')
                    count += 1
                    logger.info(count)
                except StopIteration:
                    break  # loop end
                except RateLimitExceededException:
                    search_rate_limit = g.get_rate_limit().search
                    logger.info('search remaining: {}'.format(search_rate_limit.remaining))
                    reset_timestamp = calendar.timegm(search_rate_limit.reset.timetuple())
                    # add 10 seconds to be sure the rate limit has been reset
                    sleep_time = reset_timestamp - calendar.timegm(time.gmtime()) + 10
                    time.sleep(sleep_time)
                    continue

Aqui está parte do log:

2020/01/08 23:42:09 PM - INFO - search remaining: 0

Obrigado, @Xiaoven finalmente consegui resolver isso com seu código.

Esta página foi útil?
0 / 5 - 0 avaliações