Gemini APIキー取得支援ツール(ソースコードと説明と利用ガイド)


プログラム利用ガイド
1. このプログラムの利用シーン
Google Gemini APIを使用するプロジェクトで、APIキーの取得から設定まで一括して行いたい場合に利用できます。
2. 主な機能
- 自動ブラウザ起動: Gemini APIキー発行ページを既定のブラウザで自動的に開きます。新しいタブや新しいウィンドウでの起動も選択可能です。
- セキュアな入力: APIキーの入力時は画面に表示されないため、周囲からの覗き見やスクリーンキャプチャによる情報漏洩を防止します。
- 柔軟な保存設定:
- 環境変数名: GEMINI_API_KEY、GOOGLE_API_KEY、カスタム名から選択
- 保存先: .env、.env.development、.env.production、カスタムパスから選択
- 既存設定の保護: 既存のAPIキーがある場合は上書き確認を行い、ファイルの自動バックアップ機能で設定変更時の安全性を確保します。
- Windows PowerShell対応: 保存後に.envファイルを読み込むための具体的なPowerShellコマンド例を表示します。
3. 基本的な使い方
- プログラムの実行:
コマンドプロンプトまたはPowerShellで「python ファイル名.py」を実行します。
- 環境変数名の選択:
保存する環境変数名を選択します(1: GEMINI_API_KEY、2: GOOGLE_API_KEY、3: カスタム名)。
- 保存先ファイルの選択:
APIキーを保存するファイルを選択します(1: .env、2: .env.development、3: .env.production、4: カスタムパス)。
- ブラウザの起動:
ブラウザの開き方を選択し(1: 既定モード、2: 新しいタブ、3: 新しいウィンドウ)、Enterキーでブラウザが起動します。
- APIキーの取得:
ブラウザでGoogleアカウントにログインし、「API キーを作成」をクリックしてAPIキーをコピーします。
- APIキーの入力:
コンソールでAPIキーを貼り付けます(画面には表示されません)。
- 保存の確認:
「y」を入力してAPIキーをファイルに保存します。
4. 便利な機能
- 既存キーの検出: 同じ環境変数名のAPIキーが既に存在する場合は、マスク表示で確認でき、使用か上書きかを選択できます。
- 自動バックアップ: .envファイルを変更する前に、自動的に.bakファイルとしてバックアップを作成するため、設定を間違えても元に戻すことができます。
- 入力エラーハンドリング: 不正な環境変数名を入力した場合、自動的に既定値にフォールバックし、エラーの理由を分かりやすく表示します。
- 読み込み例の表示: 保存後に、Windows PowerShellで.envファイルを環境変数として読み込むための具体的なコマンド例が表示されるため、すぐに利用を開始できます。
- 中断時の安全終了: Ctrl+Cで処理を中断した場合も、安全にプログラムが終了し、データの破損を防止します。
Python開発環境,ライブラリ類
ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。
Python 3.12 のインストール
インストール済みの場合は実行不要。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要である。
REM Python をシステム領域にインストール
winget install --scope machine --id Python.Python.3.12 -e --silent
REM Python のパス設定
set "PYTHON_PATH=C:\Program Files\Python312"
set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts"
echo "%PATH%" | find /i "%PYTHON_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_PATH%" /M >nul
echo "%PATH%" | find /i "%PYTHON_SCRIPTS_PATH%" >nul
if errorlevel 1 setx PATH "%PATH%;%PYTHON_SCRIPTS_PATH%" /M >nul
【関連する外部ページ】
Python の公式ページ: https://www.python.org/
AI エディタ Windsurf のインストール
Pythonプログラムの編集・実行には、AI エディタの利用を推奨する。ここでは,Windsurfのインストールを説明する。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行して、Windsurfをシステム全体にインストールする。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要となる。
winget install --scope machine Codeium.Windsurf -e --silent
【関連する外部ページ】
Windsurf の公式ページ: https://windsurf.com/
Gemini APIキー取得支援ツール
概要
本プログラムは、Google AI StudioのGemini APIキーを取得し、環境変数ファイル(.env)に保存する作業を支援するツールである。Windows環境での実行を前提とし、ブラウザによるAPIキー発行ページへのアクセスから、取得したキーの安全な保存まで、一連の作業を支援する。
主要技術
webbrowserモジュール
Python標準ライブラリのwebbrowserモジュールを使用し、ブラウザ制御を実現する。open()、open_new()、open_new_tab()の各関数により、ユーザーの選択に応じた方法でブラウザウィンドウを開く。
getpassモジュール
getpass.getpass()関数[2]により、APIキー入力時のエコーバックを無効化する。これにより、画面上にAPIキーが表示されることを防ぎ、セキュリティを確保する。
技術的特徴
柔軟な環境変数検出
正規表現パターンにより、.envファイル内の環境変数を検出する。export文の有無、変数名前後の空白、等号前後の空白に対応し、シェルスクリプト形式とdotenv形式の両方をサポートする。
安全なファイル更新
既存の.envファイルを更新する際、shutilモジュール[4]を用いてバックアップファイル(.env.bak)を作成する。
APIキーのマスク表示
取得したAPIキーを画面表示する際、先頭8文字と末尾4文字のみを表示し、中間部分をマスクする。短いキーの場合は全体をアスタリスクで置換し、情報漏洩を防ぐ。
実装の特色
複数の環境設定ファイル対応
開発環境と本番環境の分離を考慮し、.env、.env.development、.env.productionの各ファイル形式に対応する。カスタムファイル名の指定も可能である。
対話的インターフェース
環境変数名、保存先ファイル、ブラウザ起動方法を対話的に選択できる。既存のAPIキーが存在する場合は、使用または上書きの選択肢を提供する。
ソースコード
"""Gemini APIキー取得支援ツール
特徴技術名: webbrowserモジュール
出典: Python Software Foundation. (2025). webbrowser — Convenient web-browser controller. Python 3.13.5 documentation. https://docs.python.org/3/library/webbrowser.html
前提: 本ツールは Windows 環境での実行を前提とする。
特徴技術および学習済モデルの利用制限: Python標準ライブラリはPython Software Foundation License (PSFL)の下で提供され、商用利用を含めて自由に使用可能。学習済みモデルは使用していない。
特徴機能: 既定ブラウザの起動制御
webbrowserモジュールはプラットフォーム独立であるが、本ツールでは Windows の既定ブラウザを用いて Gemini のAPIキー発行ページを開く。
学習済みモデル: 使用していない
方式設計:
- 関連利用技術:
- getpassモジュール: 入力時のエコー無効化(環境により無効化できない場合がある)
- pathlibモジュール: オブジェクト指向パス操作とテキスト読み書き
- reモジュール: .env内の環境変数行の検出(export有無や空白を許容)
- shutilモジュール: .envのバックアップ作成
- 入力と出力:
入力:
• 環境変数名の選択(GEMINI_API_KEY/GOOGLE_API_KEY/カスタム)
• 保存先ファイルの選択(.env/.env.development/.env.production/カスタム)
• ブラウザの開き方の選択(既定/新しいタブ/新しいウィンドウ)
• コンソールでのAPIキー入力(getpass)
出力:
• Windowsの既定ブラウザでGemini APIキーページを表示
• マスクしたAPIキーの一部表示
• .envへの保存と保存先の絶対パス表示
• 保存後のWindows PowerShell向け読み込み例の表示
- 処理手順:
1. 環境変数名と保存先ファイルを選択する
2. 既存APIキーを検出し(export形式と通常形式に対応)、使用または上書きを選択する
3. ブラウザ起動方式を選択し、APIキー発行ページを開く
4. ページの案内に従いAPIキーを取得する
5. getpassでAPIキーを入力する
6. .envをバックアップし、既存の対象行を除去してから新しいキーを保存する
7. 保存結果とWindows向け読み込みガイダンスを表示する
- 前処理: 既存.envファイルの読み込みとAPIキーの存在確認
- 後処理: 保存結果の表示と読み込みガイダンス表示
- 追加処理: APIキーの部分マスク表示による情報露出の抑制
- 調整を必要とする設定値:
- 変数名: 保存する環境変数名(GEMINI_API_KEY/GOOGLE_API_KEY/カスタム)
- filename: 保存先ファイル名(.env/.env.development/.env.production/カスタム)
- ブラウザ起動モード: 既定/新しいタブ/新しいウィンドウ
将来方策: 既存の.envファイルを読み込み、同一APIキーの存在確認を行う機能は実装済みである。
その他の重要事項:
- getpassは可能な場合に入力のエコーを無効化するが、環境によっては無効化できず入力が表示される場合がある。
- webbrowser.open系の戻り値は成否を示す。環境によりブラウザが開かない場合がある。
前準備: なし(標準ライブラリのみ使用)
"""
import webbrowser
from pathlib import Path
import getpass
import re
import shutil
# 設定定数
DEFAULT_ENV_FILE = '.env'
DEFAULT_ENV_CHOICES = ['.env', '.env.development', '.env.production']
DEFAULT_KEY_CHOICES = ['GEMINI_API_KEY', 'GOOGLE_API_KEY']
GEMINI_API_URL = 'https://aistudio.google.com/app/apikey'
def on_input_abort(default=None):
"""入力中断時の共通処理。defaultが与えられた場合は既定値を返し、なければ安全終了する。"""
if default is not None:
print('入力が中断されたため既定値を用いる')
return default
print('入力が中断されたため処理を終了する')
raise SystemExit(1)
def safe_input(prompt, default=None):
return input(prompt)
def prompt_choice(header_lines, options_map, default_key):
"""数値メニューの表示と入力処理を共通化する。キーと対応値を返す。"""
for line in header_lines:
print(line)
prompt = f"選択 ({'/'.join(options_map.keys())}, 既定: {default_key}): "
key = safe_input(prompt, default=default_key).strip() or default_key
return key, options_map.get(key)
def wait_enter(prompt):
"""Enterキー待ちの共通処理。"""
safe_input(prompt)
def build_key_pattern(var_name):
"""envファイル行のパターンを生成する。先頭の空白、先頭の 'export ' の有無、'=' の前後の空白を許容する。"""
pat = r'^\s*(?:export\s+)?' + re.escape(var_name) + r'\s*='
return re.compile(pat)
def sanitize_var_name(name):
"""環境変数名を検証・サニタイズする。無効な場合は既定名にフォールバックするための情報を返す。"""
n = (name or '').strip()
# 先頭の 'export' を除去(あれば)
lowered = n.lower()
if lowered.startswith('export'):
parts = n.split(None, 1)
n = parts[1] if len(parts) == 2 else ''
# '=' を含む名称は不正(Windows仕様)
if '=' in n:
return (DEFAULT_KEY_CHOICES[0], True, "変数名に'='は使用できない")
# POSIX慣用: 先頭は英字またはアンダースコア、その後は英数字とアンダースコアのみ
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', n):
if n == '':
return (DEFAULT_KEY_CHOICES[0], True, '空の変数名')
return (DEFAULT_KEY_CHOICES[0], True, '許可文字は英字・数字・アンダースコア。先頭は英字またはアンダースコア')
return (n, False, '')
def check_api_key(filename=DEFAULT_ENV_FILE, var_name='GEMINI_API_KEY'):
"""既存のAPIキーを確認する。
.env ファイルから、先頭が "[export ]<VAR_NAME>=" の最初の行を探索し、等号以降の値(前後空白は除去)を返す。
見つからなければ None を返す。
"""
file_path = Path(filename)
if not file_path.exists():
return None
try:
content = file_path.read_text(encoding='utf-8')
pattern = build_key_pattern(var_name)
for line in content.splitlines():
if pattern.match(line):
value = line.split('=', 1)[1].strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in '"\'':
value = value[1:-1].strip()
if value:
return value
return None
except Exception as e:
print(f'ファイル読み込みエラー: {e}')
return None
def open_api_page(mode='default'):
"""Gemini の API キー発行ページを Windows の既定ブラウザで開く。
mode: 'default' | 'new_tab' | 'new_window'
webbrowser の戻り値(True/False)を返す。
"""
print('ブラウザでGeminiのAPIキー発行ページを開きます...')
funcs = {'new_tab': webbrowser.open_new_tab, 'new_window': webbrowser.open_new}
return funcs.get(mode, webbrowser.open)(GEMINI_API_URL)
def get_api_key():
"""ユーザーからAPIキーを取得する。
getpass.getpass を用いて入力を受け付ける。環境によってはエコーを無効化できない場合がある。
"""
print('コピーしたAPIキーを貼り付けてください')
api_key = getpass.getpass('APIキー: ').strip()
return api_key
def save_api_key(api_key, filename=DEFAULT_ENV_FILE, var_name='GEMINI_API_KEY'):
"""APIキーをファイルに保存する(上書きモード)。
既存ファイルがある場合は、"[export ]<VAR_NAME>=" で始まる行を除去し、その他の行は保持する。
保存前にバックアップを <filename>.bak として作成する。
"""
try:
file_path = Path(filename)
existing_lines = []
if file_path.exists():
# バックアップ作成
backup_path = Path(str(file_path) + '.bak')
try:
shutil.copyfile(file_path, backup_path)
print(f'バックアップを作成した: {backup_path}')
except Exception as be:
print(f'バックアップ作成に失敗した: {be}')
content = file_path.read_text(encoding='utf-8')
pattern = build_key_pattern(var_name)
for line in content.splitlines():
if not pattern.match(line):
existing_lines.append(line + '\n')
# 新しいAPIキーを書き出し
content = ''.join(existing_lines)
if content and not content.endswith('\n'):
content += '\n'
content += f'{var_name}={api_key}\n'
# 親ディレクトリがない場合は作成
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content, encoding='utf-8', newline='\n')
print(f'APIキーを {file_path.resolve()} に保存した')
return True
except Exception as e:
print(f'保存エラー: {e}')
return False
def mask_key(key, head=8, tail=4):
"""APIキーのマスク表示を作成する。キー長が短い場合は全体をマスクする。"""
if not key:
return ''
# キーが短い場合は全体をマスク
if len(key) <= head + tail + 3: # 最低3文字分のマスクを確保
return '*' * len(key)
return f'{key[:8]}...{key[-4:]}'
def choose_env_file():
"""保存先のenvファイルを選択する。"""
header = ['保存先ファイルを選択する']
header += [f'{i}. {name}' for i, name in enumerate(DEFAULT_ENV_CHOICES, 1)]
header += ['4. カスタムパスを指定する']
options = {'1': DEFAULT_ENV_CHOICES[0], '2': DEFAULT_ENV_CHOICES[1], '3': DEFAULT_ENV_CHOICES[2], '4': None}
key, value = prompt_choice(header, options, default_key='1')
if key in ('1', '2', '3'):
return value
else:
custom = safe_input('保存先ファイル名を入力: ', default=DEFAULT_ENV_FILE).strip()
return custom or DEFAULT_ENV_FILE
def choose_var_name():
"""保存する環境変数名を選択する。"""
header = ['保存する環境変数名を選択する']
header += [f'{i}. {name}' for i, name in enumerate(DEFAULT_KEY_CHOICES, 1)]
header += ['3. カスタム名を指定する']
options = {'1': DEFAULT_KEY_CHOICES[0], '2': DEFAULT_KEY_CHOICES[1], '3': None}
key, value = prompt_choice(header, options, default_key='1')
if key in ('1', '2'):
return value
else:
custom = safe_input('変数名を入力(例: GEMINI_API_KEY): ', default=DEFAULT_KEY_CHOICES[0]).strip()
var_name, is_fallback, reason = sanitize_var_name(custom)
if is_fallback:
print(f"無効な環境変数名のため既定名にフォールバック: 入力='{custom}' 理由={reason} → 使用名='{var_name}'")
return var_name
def choose_browser_mode():
"""ブラウザの開き方を選択する。"""
header = ['ブラウザの開き方を選択する', '1. 既定モードで開く', '2. 新しいタブで開く', '3. 新しいウィンドウで開く']
options = {'1': 'default', '2': 'new_tab', '3': 'new_window'}
_, value = prompt_choice(header, options, default_key='1')
return value or 'default'
def show_post_save_guidance(filepath):
"""保存後の参考情報を表示する(Windows)。"""
print('\n=== 利用の参考情報(Windows) ===')
resolved = str(Path(filepath).resolve())
print(f'保存パス: {resolved}')
print('- Windows PowerShell の例:')
print(f' Get-Content "{resolved}" | ForEach-Object {{')
print(" if ($_ -match '^(?<k>[^#=]+)\\s*=\\s*(?<v>.*)$') { [System.Environment]::SetEnvironmentVariable($matches.k.Trim(), $matches.v.Trim()) }")
print(' }')
print('======================\n')
def main():
print('=== Gemini APIキー取得支援ツール ===\n')
# 変数名と保存先ファイルを選択
var_name = choose_var_name()
env_file = choose_env_file()
# 既存のAPIキーを確認
existing_key = check_api_key(env_file, var_name)
if existing_key:
print(f'既存のAPIキーが見つかった: {mask_key(existing_key)}')
print('1. 既存のAPIキーを使用する')
print('2. 新しいAPIキーで上書きする')
choice = input('選択 (1/2, 既定: 1): ').strip() or '1'
if choice == '1':
print('既存のAPIキーを使用する')
print('\n処理を終了する')
return
elif choice != '2':
print('無効な選択であるため処理を終了する')
return
# ブラウザを開く
mode = choose_browser_mode()
input('Enterキーでブラウザを開く...')
opened = open_api_page(mode)
if not opened:
print('ブラウザを開けなかった可能性がある。URL を手動で開くこと: ' + GEMINI_API_URL)
# 手動操作の指示を表示する。画面上の文言は変更される可能性があるため、ページの案内に従って操作すること。(旧show_instructionsの仕様)
print('\n=== 手動操作の手順 ===')
print('1. ブラウザでGoogleアカウントにログインする')
print("2. 'API キーを作成(Create API key)' をクリック")
print('3. 既存のプロジェクトを選択し、「既存のプロジェクトで API キーを作成」をクリック')
print('4. 表示されたAPIキーをコピーする')
print('=====================================\n')
# APIキー取得の確認
input('APIキーをコピーしたらEnterキーを押す...')
# APIキーを取得
api_key = get_api_key()
if api_key:
print(f'\n取得したAPIキー: {mask_key(api_key)}')
# ファイルに保存
save_choice = input('\nファイルに保存しますか? (y/n): ').strip().lower()
if save_choice == 'y':
saved = save_api_key(api_key, env_file, var_name)
if saved:
show_post_save_guidance(env_file)
else:
print('APIキーが入力されなかった')
print('\n処理を終了する')
if __name__ == '__main__':
try:
main()
except (KeyboardInterrupt, EOFError):
print('\n処理を中断しました。プログラムを終了します。')