Обзор GitHub REST API
Библиотека PyGitHub, персональные токены доступа и ограничения частоты запросов API.
«Обзор GitHub REST API» — бесплатный урок AI Agents на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Agents, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Agents содержит 4 уроков всего.
PyGitHub — Python-клиент GitHub
PyGitHub — самая популярная библиотека Python для REST API GitHub. Она превращает необработанный HTTP API в объекты Python, представляющие репозитории, задачи, PR, коммиты и пользователей. Почти любая задача автоматизации GitHub начинается с Github(token=) и g.get_repo().
# Install: pip install PyGitHub
from github import Github
import os
# Authenticate with a personal access token
g = Github(token=os.environ['GITHUB_TOKEN'])
# Get the authenticated user
user = g.get_user()
print(f'Logged in as: {user.login}')
print(f'Name: {user.name}')
print(f'Public repos: {user.public_repos}')
# Get a specific repository
repo = g.get_repo('octocat/Hello-World')
print(f'Repo: {repo.full_name}')
print(f'Stars: {repo.stargazers_count}')Аутентификация: персональный токен доступа
Самый простой способ аутентификации — персональный токен доступа (PAT), то есть долгосрочный токен, связанный с Вашей учётной записью GitHub. Создайте его в разделе github.com → Settings → Developer settings → Personal access tokens. Храните его в переменной окружения, а не в коде. Для большей безопасности используйте PAT с детализированными разрешениями и ограничьте его конкретными репозиториями.
from github import Github, Auth
import os
# Method 1: Classic token (works with PyGitHub)
token = os.environ['GITHUB_TOKEN']
g = Github(token=token)
# Method 2: Auth object (recommended for PyGitHub >= 1.59)
auth = Auth.Token(os.environ['GITHUB_TOKEN'])
g = Github(auth=auth)
# Test authentication
try:
user = g.get_user()
print(f'Authenticated as {user.login}')
except Exception as e:
print(f'Auth failed: {e}')
print('Check: Is GITHUB_TOKEN set? Has it expired?')
g.close() # close the connection when doneАутентификация приложения GitHub
Для рабочих агентов предпочтительнее использовать приложения GitHub, а не PAT. Они поддерживают детализированные разрешения, могут устанавливаться в конкретные репозитории и используют краткосрочные токены установки, которые автоматически обновляются. Используйте github.GithubIntegration для создания токенов установки.
import os
import github
APP_ID = os.environ['GITHUB_APP_ID']
PRIVATE_KEY = os.environ['GITHUB_APP_PRIVATE_KEY'] # PEM content
INSTALLATION_ID = os.environ['GITHUB_INSTALLATION_ID']
# Create GitHub App client
auth = github.Auth.AppAuth(APP_ID, PRIVATE_KEY)
gi = github.GithubIntegration(auth=auth)
# Get installation access token (expires in 1 hour)
installation = gi.get_installation(int(INSTALLATION_ID))
access_token = gi.get_access_token(int(INSTALLATION_ID))
# Use the token with a standard Github client
g = github.Github(token=access_token.token)
print(f'App authenticated, token expires: {access_token.expires_at}')Ограничения запросов: 5000 запросов в час
REST API GitHub разрешает 5 000 запросов в час для аутентифицированных пользователей. Учитывается каждый вызов API, включая вызовы с пагинацией. Проверяйте оставшуюся квоту перед пакетными операциями: после её исчерпания все запросы будут возвращать 403 Forbidden, пока ограничение запросов не сбросится.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Check current rate limit status
rate_limit = g.get_rate_limit()
core = rate_limit.core
print(f'Remaining: {core.remaining}/{core.limit} requests')
print(f'Resets at: {core.reset}')
# Calculate time until reset
import datetime
now = datetime.datetime.utcnow()
reset_in = (core.reset.replace(tzinfo=None) - now).seconds
print(f'Reset in: {reset_in // 60}m {reset_in % 60}s')
# Check before heavy operations
if core.remaining < 100:
print('WARNING: Rate limit nearly exhausted!')Получение объекта репозитория
Объект repo — отправная точка почти для всех операций GitHub. Получите его с помощью g.get_repo('owner/name'). Он содержит метаданные (звёзды, форки, описание и видимость), а также методы для доступа к задачам, PR, коммитам, выпускам и другим объектам.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Repository metadata
print(f'Full name: {repo.full_name}')
print(f'Description: {repo.description}')
print(f'Default branch: {repo.default_branch}')
print(f'Stars: {repo.stargazers_count}')
print(f'Forks: {repo.forks_count}')
print(f'Open issues: {repo.open_issues_count}')
print(f'Private: {repo.private}')
print(f'Language: {repo.language}')
print(f'Created: {repo.created_at}')
print(f'Last push: {repo.pushed_at}')Пагинация API — PaginatedList
Вызовы API GitHub, возвращающие множество элементов (задачи, коммиты и PR), возвращают объект PaginatedList. Его можно перебирать как обычный список: PyGitHub автоматически загружает страницы по мере перебора. Однако вызов len() для PaginatedList загружает все страницы, что может быть затратным.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# PaginatedList: fetch pages lazily as you iterate
issues = repo.get_issues(state='open') # returns PaginatedList
# Iterate — fetches pages 30 at a time automatically
for issue in issues:
print(f'#{issue.number}: {issue.title}')
# Get first N items without fetching everything
first_10 = list(issues[:10]) # only fetches first page
# Count (WARNING: fetches ALL pages)
total_open = issues.totalCount # uses the count from API metadata, not iterationОбработка исключений, связанных с ограничением запросов
При превышении ограничения запросов PyGitHub вызывает исключение github.GithubException.RateLimitExceededException. Обработайте его: проверьте время сброса и приостановите выполнение до снятия ограничения. Встройте эту логику в оболочку для повторных попыток, чтобы сделать любой вызов GitHub устойчивым к сбоям.
from github import Github
from github.GithubException import RateLimitExceededException
import os
import time
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
def github_call_with_rate_limit(func, *args, **kwargs):
while True:
try:
return func(*args, **kwargs)
except RateLimitExceededException:
rate_limit = g.get_rate_limit()
reset_time = rate_limit.core.reset.replace(tzinfo=None)
now = datetime.datetime.utcnow()
wait_seconds = (reset_time - now).total_seconds() + 10
print(f'Rate limit exceeded. Sleeping {wait_seconds:.0f}s until reset...')
time.sleep(max(wait_seconds, 1))
# Usage
repo = github_call_with_rate_limit(
g.get_repo, 'myorg/myrepo'
)Поиск по GitHub
Используйте g.search_issues(), g.search_repositories() и g.search_code(), чтобы выполнять поиск GitHub по всем общедоступным и Вашим закрытым репозиториям. Эти методы используют API поиска с отдельным ограничением — 30 запросов в минуту.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
# Search issues across all your repos
results = g.search_issues(
query='is:open is:issue label:bug user:myorg',
sort='created',
order='desc'
)
print(f'Found {results.totalCount} open bugs')
for issue in results[:10]:
print(f'{issue.repository.full_name}#{issue.number}: {issue.title}')
# Search for repos using a specific package
repos = g.search_repositories(
query='topic:machine-learning language:python stars:>100'
)
for repo in repos[:5]:
print(f'{repo.full_name}: {repo.stargazers_count} stars')Работа с несколькими репозиториями
Агентам часто требуется работать с несколькими репозиториями организации. Используйте g.get_organization(), чтобы получить список всех репозиториев организации, а затем обработайте их в цикле. Фильтруйте их по языку, статусу архивации или дате активности, чтобы не обрабатывать неактивные репозитории.
from github import Github
import os
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
org = g.get_organization('myorg')
# Get all active Python repos
cutoff = datetime.datetime.now() - datetime.timedelta(days=180)
active_repos = [
repo
for repo in org.get_repos(type='all')
if (
not repo.archived
and repo.language == 'Python'
and repo.pushed_at
and repo.pushed_at.replace(tzinfo=None) > cutoff
)
]
print(f'Active Python repos: {len(active_repos)}')
for repo in active_repos[:5]:
print(f' {repo.name}: last push {repo.pushed_at.date()}')Чтение содержимого файла из репозитория
Используйте repo.get_contents(path), чтобы прочитать любой файл из репозитория. Содержимое закодировано в base64, но PyGitHub автоматически декодирует его через свойство .decoded_content. Укажите ветку или SHA коммита с помощью параметра ref.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Read a file from the default branch
contents = repo.get_contents('README.md')
readme_text = contents.decoded_content.decode('utf-8')
print(f'README ({len(readme_text)} chars):')
print(readme_text[:200])
# Read from a specific branch
requirements = repo.get_contents(
'requirements.txt',
ref='feature/new-deps'
)
deps = requirements.decoded_content.decode('utf-8')
print('Dependencies:', deps[:300])Обработка распространённых исключений GitHub
PyGitHub вызывает GithubException для всех ошибок API. Распространённые подклассы: UnknownObjectException (404 — репозиторий или задача не найдены), BadCredentialsException (401 — недействительный токен) и RateLimitExceededException (403 — превышено ограничение запросов). Всегда перехватывайте их отдельно.
from github import Github
from github.GithubException import (
GithubException, UnknownObjectException,
BadCredentialsException, RateLimitExceededException
)
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
def get_repo_safely(repo_full_name):
try:
return g.get_repo(repo_full_name)
except BadCredentialsException:
print('ERROR: GitHub token is invalid or expired')
return None
except UnknownObjectException:
print(f'ERROR: Repo not found: {repo_full_name}')
print('Check: typo in name? Private repo you can\'t access?')
return None
except RateLimitExceededException:
print('ERROR: GitHub rate limit exceeded, retry later')
return None
except GithubException as e:
print(f'GitHub API error {e.status}: {e.data}')
return NoneБыстрая проверка: ограничение запросов
Проверьте своё понимание ограничений запросов API GitHub.
Итоги: REST API GitHub
Теперь Вы умеете подключаться к GitHub с помощью PyGitHub:
- Github(token=) или Github(auth=Auth.Token(...)) для аутентификации с помощью PAT
- Приложения GitHub с
GithubIntegrationдля рабочих агентов с детализированными разрешениями - Ограничение запросов: 5 000 запросов в час; проверяйте его с помощью
g.get_rate_limit()и обрабатывайтеRateLimitExceededException - PaginatedList: перебирайте элементы лениво; используйте
.totalCount, чтобы получить количество без загрузки всех страниц - g.get_repo('owner/name') — отправная точка для операций на уровне репозитория
- Явно перехватывайте
UnknownObjectException(404) иBadCredentialsException(401)
Часто задаваемые вопросы
Урок «Обзор GitHub REST API» бесплатный?
Да — полный текст урока «Обзор GitHub REST API» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Agents, подпишись на CoddyKit PRO. Курс AI Agents содержит 4 уроков всего.
Чему я научусь в уроке «Обзор GitHub REST API»?
Библиотека PyGitHub, персональные токены доступа и ограничения частоты запросов API. Ты практикуешь AI Agents с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Agents?
Предыдущий опыт не требуется. AI Agents на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Обзор GitHub REST API»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Agents?
Да. Каждый урок AI Agents включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обзор GitHub REST API
- Просмотр и управление задачами
- Автоматические комментарии к проверке PR
- История коммитов и анализ различий