Pygithub: ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ограничСния скорости поиска

Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π½Π° 10 Π°ΠΏΡ€. 2017  Β·  13ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ  Β·  Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: PyGithub/PyGithub

ΠŸΠΎΡ…ΠΎΠΆΠ΅, Ρ‡Ρ‚ΠΎ функция get_rate_limit Π²Π΅Ρ€Π½Π΅Ρ‚ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Github считаСт «основным» ΠΏΡ€Π΅Π΄Π΅Π»ΠΎΠΌ скорости. Однако ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ Ρ€Π°Π·Π½Ρ‹Π΅ ограничСния скорости поиска ΠΊΠΎΠ΄Π°. Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ здСсь .

Насколько я ΠΌΠΎΠ³Ρƒ ΡΡƒΠ΄ΠΈΡ‚ΡŒ, сСйчас Π½Π΅Ρ‚ способа ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ограничСния скорости ΠΊΠΎΠ΄Π° поиска.

Π‘Π°ΠΌΡ‹ΠΉ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Для людСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ сюда ΠΈΠ· поисковой систСмы, я Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ» Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ @bbi-yggy:

from datetime import datetime, timezone

def rate_limited_retry(github):
    def decorator(func):
        def ret(*args, **kwargs):
            for _ in range(3):
                try:
                    return func(*args, **kwargs)
                except RateLimitExceededException:
                    limits = github.get_rate_limit()
                    reset = limits.search.reset.replace(tzinfo=timezone.utc)
                    now = datetime.now(timezone.utc)
                    seconds = (reset - now).total_seconds()
                    print(f"Rate limit exceeded")
                    print(f"Reset is in {seconds:.3g} seconds.")
                    if seconds > 0.0:
                        print(f"Waiting for {seconds:.3g} seconds...")
                        time.sleep(seconds)
                        print("Done waiting - resume!")
            raise Exception("Failed too many times")
        return ret
    return decorator

Π­Ρ‚Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

@rate_limited_retry(github)
def run_query(import_string):
    query_string = f"language:Python \"{import_string}\""
    return list(github.search_code(query_string))

results = run_query(import_string)

ВсС 13 ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π― Π²ΠΈΠΆΡƒ Ρ‚Ρƒ ΠΆΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ. Π’ΠΎΡ‚ нСбольшой скрипт, ΠΈΠ»Π»ΡŽΡΡ‚Ρ€ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ.

import os
from datetime import datetime
from github import Github

# Login
TOKEN = os.getenv("GITHUB_ACCESS_TOKEN")
github = Github(TOKEN)

# Get initial rate limit and reset time
rl1 = github.get_rate_limit().rate
print("RL1 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl1.limit, rl1.remaining, rl1.reset))
# RL1 | Limit: 5000, Remaining: 5000, Reset: 2017-09-22 17:26:35.

# Perform a search
results = github.search_code("Hello World")

# Rate limit of Github instance is unchanged after a search
rl2 = github.get_rate_limit().rate
print("RL2 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl2.limit, rl2.remaining, rl2.reset))
# RL2 | Limit: 5000, Remaining: 5000, Reset: 2017-09-22 17:26:35.

# The PaginatedList instance has a Requestor with the same info
rl3 = results._PaginatedList__requester.rate_limiting
rl3_reset = datetime.utcfromtimestamp(int(
        results._PaginatedList__requester.rate_limiting_resettime))
print("RL3 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl3[0], rl3[1], rl3_reset))
# RL3 | Limit: 5000, Remaining: 5000, Reset: 2017-09-22 17:26:35.

# However, the actual ContentFile results show a different limit
# The Requester of each individual result ...
result = results[0]
rl4 = result._requester.rate_limiting
rl4_reset = datetime.utcfromtimestamp(int(
        result._requester.rate_limiting_resettime))
print("RL4 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl4[1], rl4[0], rl4_reset))
# RL4 | Limit: 30, Remaining: 29, Reset: 2017-09-22 16:27:36.

# ... and headers stored in the content file directly show a different rate limit.
rl5_limit = result._headers['x-ratelimit-limit']
rl5_remaining = result._headers['x-ratelimit-remaining']
rl5_reset = datetime.utcfromtimestamp(int(
        result._headers['x-ratelimit-reset']))
print("RL5 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl5_limit, rl5_remaining, rl5_reset))
# RL5 | Limit: 30, Remaining: 29, Reset: 2017-09-22 16:27:36.

# In the end, the main Github instance still shows the original full rate limit
rl6 = github.get_rate_limit().rate
print("RL6 | Limit: {}, Remaining: {}, Reset: {}.".format(
    rl6.limit, rl6.remaining, rl6.reset))
# RL6 | Limit: 5000, Remaining: 5000, Reset: 2017-09-22 17:26:35.

+1 Π­Ρ‚Π° функция Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° для прилоТСния, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ я ΠΏΡ‹Ρ‚Π°ΡŽΡΡŒ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ.

@brentshermana для вашСго прилоТСния, рассмотритС Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ограничСния скорости (послСднСго ΠΎΡ‚Π²Π΅Ρ‚Π°; см. Мой ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π²Ρ‹ΡˆΠ΅) ΠΈΠ»ΠΈ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ опроса ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΉ Ρ‚ΠΎΡ‡ΠΊΠΈ /rate_limit . Π­Ρ‚ΠΎ содСрТит ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ±ΠΎ всСх Π²ΠΈΠ΄Π°Ρ… ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ скорости ΠΈ Π½Π΅ засчитываСтся Π² ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости.

Π’ ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ², Π±Ρ‹Π»ΠΎ Π±Ρ‹ Π½Π΅ΠΏΠ»ΠΎΡ…ΠΎ, Ссли Π±Ρ‹ PyGithub Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π» rate , Π½ΠΎ ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π» resources ΠΈΠ· Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ /rate_limit . Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ Π΅ΡΡ‚ΡŒ, ΠΊ соТалСнию, ΠΎΠ½Π° Π½Π΅ доступна для ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ.

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, список с Ρ€Π°Π·Π±ΠΈΠ²ΠΊΠΎΠΉ Π½Π° страницы Π΄ΠΎΠ»ΠΆΠ΅Π½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости поиска ΠΏΠΎ ΠΊΠΎΠ΄Ρƒ, Ссли ΠΎΠ½ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Ρ‚Π°ΠΊΠΎΠ³ΠΎ поиска, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ всС, Ρ‡Ρ‚ΠΎ хранится Π² _headers['x-ratelimit-*'] .

ΠšΡΡ‚Π°Ρ‚ΠΈ: я Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ Π·Π°ΠΌΠ΅Ρ‚ΠΈΠ», Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ»Π΅ rate ΠΈΠ· JSON, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ /rate_limit , устарСло, Π° информация Π² resources являСтся Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌΠΎΠΉ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²ΠΎΠΉ: https://developer.github.com/ v3/rate_limit/#deprecation -ΡƒΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠ΅

Π― дСлаю ΠΈΠΌΠ΅Π½Π½ΠΎ это. Если ΠΊΡ‚ΠΎ-Ρ‚ΠΎ Ρ…ΠΎΡ‡Π΅Ρ‚ Π°Π΄Π°ΠΏΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ это ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚Π°Ρ‚ΡŒΡΡ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ запрос Π½Π° вытягиваниС, я благословляю вас:

def wait(seconds):
    print("Waiting for {} seconds ...".format(seconds))
    time.sleep(seconds)
    print("Done waiting - resume!")

def api_wait():
    url = 'https://api.github.com/rate_limit'
    response = urlopen(url).read()
    data = json.loads(response.decode())
    if data['resources']['core']['remaining'] <= 10:  # extra margin of safety
        reset_time = data['resources']['core']['reset']
        wait(reset_time - time.time() + 10)
    elif data['resources']['search']['remaining'] <= 2:
        reset_time = data['resources']['search']['reset']
        wait(reset_time - time.time() + 10)

Π― столкнулся с ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ, ΠΊΠΎΠ³Π΄Π° моя итСрация ΠΏΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ search_issues останавливаСтся послС 1020 Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ², ΠΊΠΎΠ³Π΄Π° Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ 1869 Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ². Мой скрипт ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· останавливаСтся Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈ Ρ‚ΠΎΠΌ ΠΆΠ΅ мСстС. ΠœΠΎΠΆΠ΅Ρ‚ Π»ΠΈ это Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ ограничСния скорости?

Π― Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ просто Π·Π°ΠΊΠ°Π½Ρ‡ΠΈΠ²Π°ΡŽΡ‚ΡΡ. Если я ΠΏΠΎΠΌΠ΅Ρ‰Ρƒ свою строку запроса нСпосрСдствСнно Π² Π²Π΅Π±-интСрфСйс GitHub, я ΡƒΠ²ΠΈΠΆΡƒ всС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ 1869, ΠΊΠ°ΠΊ ΠΈ оТидалось. 1020 ΠΊΡ€Π°Ρ‚Π½ΠΎ 30, Ρ‡Ρ‚ΠΎ заставляСт мСня Π·Π°Π΄ΡƒΠΌΠ°Ρ‚ΡŒΡΡ, Π½Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π»ΠΈ это с Π½ΡƒΠΌΠ΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ страниц?

Код выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

querystring = "type:pr is:closed repo:xxxx closed:2017-07-01..2018-06-30"
issues = git.search_issues(query=querystring, sort="updated", order="asc")
for issue in issues:
    pull = issue.as_pull_request()
    print "%s: %s" % (pull.number, pull.title)

Π‘ΠΎΠ»ΡŒΡˆΠΎΠ΅ спасибо Π·Π° Π»ΡŽΠ±Ρ‹Π΅ совСты, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ΄Π΅Π»ΠΈΡ‚ΡŒΡΡ, ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ здСсь ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠΉΡ‚ΠΈ Π½Π΅ Ρ‚Π°ΠΊ.

Π― Ρ‚Π°ΠΊΠΆΠ΅ попытался ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΈΡ‚ΡŒ issues.reversed , Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ, начнСтся Π»ΠΈ ΠΎΠ½ Π² ΠΊΠΎΠ½Ρ†Π΅ ΠΌΠΎΠΈΡ… ΠΎΠΆΠΈΠ΄Π°Π΅ΠΌΡ‹Ρ… Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² 1869. Однако Π² этом случаС я ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 30 вопросов с ΠΏΠ΅Ρ€Π²ΠΎΠΉ страницы Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ².

Π”Π°Π»ΡŒΠ½Π΅ΠΉΡˆΠ΅Π΅ расслСдованиС ΠΏΠΎΠΊΠ°Π·Π°Π»ΠΎ, Ρ‡Ρ‚ΠΎ я ΡƒΠΏΠΈΡ€Π°ΡŽΡΡŒ Π² 1000 Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Π½Π° поисковый Π»ΠΈΠΌΠΈΡ‚ .

Как насчСт Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΌΡ‹ прСдоставили Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΌΠ΅Ρ‚ΠΎΠ΄ get_search_rate_limit() для ограничСния скорости поиска, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ get_rate_limit() Π±ΡƒΠ΄Π΅Ρ‚ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ послСднСС «основноС» ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости, ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ Github: https://developer.github.com/ v3/rate_limit/

ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости поиска API ΠΈ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости GraphQL ΡƒΠΆΠ΅ доступны. Один ΠΌΠ΅Ρ‚ΠΎΠ΄ для всСх.

По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΎΠ½ ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ Π²Π°ΠΌ «основной» ΠΏΡ€Π΅Π΄Π΅Π» скорости. Π’Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости поиска/Π³Ρ€Π°Ρ„ΠΈΠΊΠ°, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΠ²ΡˆΠΈΡΡŒ ΠΊ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌ.

r = g.get_rate_limit()
>>> r
RateLimit(core=Rate(remaining=4923, limit=5000))
>>> r.search
Rate(remaining=30, limit=30)
>>> r.graphql
Rate(remaining=5000, limit=5000)

Выглядит ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ, спасибо @sfdye!

Π§Ρ‚ΠΎΠ±Ρ‹ ΡΠΌΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ оТидания @brentshermana , Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ΠΌ скорости поиска, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ Π²Ρ€ΠΎΠ΄Π΅ этого:

from datetime import datetime

def api_wait_search(git):
  limits = git.get_rate_limit()
  if limits.search.remaining <= 2:
    seconds = (limits.search.reset - datetime.now()).total_seconds()
    print "Waiting for %d seconds ..." % (seconds)
    time.sleep(seconds)
    print "Done waiting - resume!"

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π²Ρ‹Π·ΠΎΠ² get_rate_limit() Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ Π½Π΅Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Π·Π°Π΄Π΅Ρ€ΠΆΠΊΡƒ, поэтому Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ свСсти ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌΡƒ частоту Π΅Π³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π°.

Для людСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‚ сюда ΠΈΠ· поисковой систСмы, я Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ» Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ @bbi-yggy:

from datetime import datetime, timezone

def rate_limited_retry(github):
    def decorator(func):
        def ret(*args, **kwargs):
            for _ in range(3):
                try:
                    return func(*args, **kwargs)
                except RateLimitExceededException:
                    limits = github.get_rate_limit()
                    reset = limits.search.reset.replace(tzinfo=timezone.utc)
                    now = datetime.now(timezone.utc)
                    seconds = (reset - now).total_seconds()
                    print(f"Rate limit exceeded")
                    print(f"Reset is in {seconds:.3g} seconds.")
                    if seconds > 0.0:
                        print(f"Waiting for {seconds:.3g} seconds...")
                        time.sleep(seconds)
                        print("Done waiting - resume!")
            raise Exception("Failed too many times")
        return ret
    return decorator

Π­Ρ‚Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

@rate_limited_retry(github)
def run_query(import_string):
    query_string = f"language:Python \"{import_string}\""
    return list(github.search_code(query_string))

results = run_query(import_string)

ΠœΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Π°Ρ вСрсия Π΄Π΅ΠΊΠΎΡ€Π°Ρ‚ΠΎΡ€Π° pokey Π²Ρ‹ΡˆΠ΅, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΡ‡Π΅ΡΡ‚ΡŒ core/search/graphql.
Π’Π°ΠΊΠΆΠ΅ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° ​​30-сСкундная Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠ°, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ Github Π½Π΅ сбрасываСт ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠ΅ скорости Ρ‚ΠΎΡ‡Π½ΠΎ Π² ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ врСмя.

def rate_limited_retry():
    def decorator(func):
        def ret(*args, **kwargs):
            for _ in range(3):
                try:
                    return func(*args, **kwargs)
                except RateLimitExceededException:
                    limits = gh.get_rate_limit()
                    print(f"Rate limit exceeded")
                    print("Search:", limits.search, "Core:", limits.core, "GraphQl:", limits.graphql)

                    if limits.search.remaining == 0:
                        limited = limits.search
                    elif limits.graphql.remaining == 0:
                        limited = limits.graphql
                    else:
                        limited = limits.core
                    reset = limited.reset.replace(tzinfo=timezone.utc)
                    now = datetime.now(timezone.utc)
                    seconds = (reset - now).total_seconds() + 30
                    print(f"Reset is in {seconds} seconds.")
                    if seconds > 0.0:
                        print(f"Waiting for {seconds} seconds...")
                        time.sleep(seconds)
                        print("Done waiting - resume!")
            raise Exception("Failed too many times")
        return ret
    return decorator

Π‘Ρ‹Π»Π° Π»ΠΈ эта страница ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ?
0 / 5 - 0 Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ΠΈ