Python to Go Transpiler

PythonからGoへのトランスパイルGUIアプリを作成します。Claude APIを使用した高品質な変換システムを実装します。

 

次に、依存関係を記載したrequirements.txtファイルを作成します。

 

次に、使い方を説明するREADMEファイルを作成します。

 

それでは、ファイルを出力ディレクトリに移動します。

 

PythonからGoへのトランスパイルGUIアプリを作成しました。

 

## 主な機能

 

1. **2ペイン構成**: 左側にPythonコード、右側にGoコードを表示

2. **Claude AI連携**: Sonnet 4を使用した高精度な変換

3. **ファイル操作**: Pythonファイルの読み込み・Goファイルの保存

4. **非同期処理**: 変換中もUIがフリーズしない設計

5. **サンプルコード**: フィボナッチ数列のサンプル付き

 

## セットアップ

 

```bash

pip install -r requirements.txt

python python_to_go_transpiler.py

```

 

アプリ起動後、Anthropic API Keyを設定して使用できます。環境変数`ANTHROPIC_API_KEY`に設定しておくと自動で読み込まれます。

 

#!/usr/bin/env python3
"""
Python to Go Transpiler GUI Application
PythonコードをGoコードに変換するGUIアプリケーション
"""

import tkinter as tk
from tkinter import ttk, scrolledtext, filedialog, messagebox
import anthropic
import os
import threading
from pathlib import Path


class PythonToGoTranspiler:
    def __init__(self, root):
        self.root = root
        self.root.title("Python → Go トランスパイラ")
        self.root.geometry("1400x900")
        
        # Anthropic APIクライアントの初期化
        self.client = None
        self.api_key = os.environ.get("ANTHROPIC_API_KEY", "")
        
        self.setup_ui()
        
    def setup_ui(self):
        # メインフレーム
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # ウィンドウのグリッド設定
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(0, weight=1)
        main_frame.rowconfigure(2, weight=1)
        
        # タイトル
        title_label = ttk.Label(
            main_frame, 
            text="Python → Go トランスパイラ",
            font=("Arial", 16, "bold")
        )
        title_label.grid(row=0, column=0, pady=(0, 10))
        
        # API Key入力セクション
        api_frame = ttk.LabelFrame(main_frame, text="設定", padding="10")
        api_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        api_frame.columnconfigure(1, weight=1)
        
        ttk.Label(api_frame, text="Anthropic API Key:").grid(row=0, column=0, sticky=tk.W, padx=(0, 5))
        self.api_key_entry = ttk.Entry(api_frame, show="*", width=50)
        self.api_key_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), padx=(0, 5))
        self.api_key_entry.insert(0, self.api_key)
        
        ttk.Button(api_frame, text="API Key設定", command=self.set_api_key).grid(row=0, column=2)
        
        # メインコンテンツエリア
        content_frame = ttk.Frame(main_frame)
        content_frame.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        content_frame.columnconfigure(0, weight=1)
        content_frame.columnconfigure(1, weight=1)
        content_frame.rowconfigure(0, weight=1)
        
        # 左側: Pythonコード入力
        left_frame = ttk.LabelFrame(content_frame, text="Pythonコード入力", padding="10")
        left_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 5))
        left_frame.columnconfigure(0, weight=1)
        left_frame.rowconfigure(1, weight=1)
        
        # ボタンフレーム(左)
        left_btn_frame = ttk.Frame(left_frame)
        left_btn_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 5))
        
        ttk.Button(left_btn_frame, text="ファイルを開く", command=self.load_python_file).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(left_btn_frame, text="クリア", command=self.clear_python_code).pack(side=tk.LEFT)
        
        # Pythonコードテキストエリア
        self.python_text = scrolledtext.ScrolledText(
            left_frame,
            wrap=tk.WORD,
            width=60,
            height=30,
            font=("Consolas", 10)
        )
        self.python_text.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # サンプルコードを挿入
        sample_code = '''def fibonacci(n):
    """フィボナッチ数列を生成"""
    if n <= 0:
        return []
    elif n == 1:
        return [0]
    elif n == 2:
        return [0, 1]
    
    fib = [0, 1]
    for i in range(2, n):
        fib.append(fib[i-1] + fib[i-2])
    return fib

def main():
    result = fibonacci(10)
    print(f"Fibonacci sequence: {result}")
    
if __name__ == "__main__":
    main()
'''
        self.python_text.insert("1.0", sample_code)
        
        # 右側: Goコード出力
        right_frame = ttk.LabelFrame(content_frame, text="Goコード出力", padding="10")
        right_frame.grid(row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(5, 0))
        right_frame.columnconfigure(0, weight=1)
        right_frame.rowconfigure(1, weight=1)
        
        # ボタンフレーム(右)
        right_btn_frame = ttk.Frame(right_frame)
        right_btn_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 5))
        
        ttk.Button(right_btn_frame, text="保存", command=self.save_go_file).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(right_btn_frame, text="クリア", command=self.clear_go_code).pack(side=tk.LEFT)
        
        # Goコードテキストエリア
        self.go_text = scrolledtext.ScrolledText(
            right_frame,
            wrap=tk.WORD,
            width=60,
            height=30,
            font=("Consolas", 10)
        )
        self.go_text.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 下部: 変換ボタンとステータス
        bottom_frame = ttk.Frame(main_frame)
        bottom_frame.grid(row=3, column=0, sticky=(tk.W, tk.E), pady=(10, 0))
        bottom_frame.columnconfigure(0, weight=1)
        
        # 変換ボタン
        self.transpile_btn = ttk.Button(
            bottom_frame,
            text="🔄 Goに変換",
            command=self.start_transpile,
            style="Accent.TButton"
        )
        self.transpile_btn.grid(row=0, column=0, pady=(0, 10))
        
        # プログレスバー
        self.progress = ttk.Progressbar(bottom_frame, mode='indeterminate')
        self.progress.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 5))
        
        # ステータスバー
        self.status_label = ttk.Label(bottom_frame, text="準備完了", relief=tk.SUNKEN, anchor=tk.W)
        self.status_label.grid(row=2, column=0, sticky=(tk.W, tk.E))
        
    def set_api_key(self):
        """API Keyを設定"""
        api_key = self.api_key_entry.get().strip()
        if not api_key:
            messagebox.showwarning("警告", "API Keyを入力してください")
            return
        
        try:
            self.client = anthropic.Anthropic(api_key=api_key)
            self.api_key = api_key
            messagebox.showinfo("成功", "API Keyが設定されました")
            self.update_status("API Key設定完了")
        except Exception as e:
            messagebox.showerror("エラー", f"API Key設定エラー: {str(e)}")
    
    def load_python_file(self):
        """Pythonファイルを読み込む"""
        filename = filedialog.askopenfilename(
            title="Pythonファイルを選択",
            filetypes=[("Python files", "*.py"), ("All files", "*.*")]
        )
        if filename:
            try:
                with open(filename, 'r', encoding='utf-8') as f:
                    content = f.read()
                self.python_text.delete("1.0", tk.END)
                self.python_text.insert("1.0", content)
                self.update_status(f"読み込み完了: {Path(filename).name}")
            except Exception as e:
                messagebox.showerror("エラー", f"ファイル読み込みエラー: {str(e)}")
    
    def save_go_file(self):
        """Goファイルを保存"""
        content = self.go_text.get("1.0", tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "保存するコードがありません")
            return
        
        filename = filedialog.asksaveasfilename(
            title="Goファイルを保存",
            defaultextension=".go",
            filetypes=[("Go files", "*.go"), ("All files", "*.*")]
        )
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(content)
                self.update_status(f"保存完了: {Path(filename).name}")
                messagebox.showinfo("成功", "ファイルを保存しました")
            except Exception as e:
                messagebox.showerror("エラー", f"ファイル保存エラー: {str(e)}")
    
    def clear_python_code(self):
        """Pythonコードをクリア"""
        self.python_text.delete("1.0", tk.END)
        self.update_status("Pythonコードをクリアしました")
    
    def clear_go_code(self):
        """Goコードをクリア"""
        self.go_text.delete("1.0", tk.END)
        self.update_status("Goコードをクリアしました")
    
    def update_status(self, message):
        """ステータスメッセージを更新"""
        self.status_label.config(text=message)
        self.root.update_idletasks()
    
    def start_transpile(self):
        """変換処理を開始(別スレッドで実行)"""
        if not self.client:
            messagebox.showwarning("警告", "先にAPI Keyを設定してください")
            return
        
        python_code = self.python_text.get("1.0", tk.END).strip()
        if not python_code:
            messagebox.showwarning("警告", "Pythonコードを入力してください")
            return
        
        # UIを無効化
        self.transpile_btn.config(state=tk.DISABLED)
        self.progress.start()
        self.update_status("変換中...")
        
        # 別スレッドで変換実行
        thread = threading.Thread(target=self.transpile_code, args=(python_code,))
        thread.daemon = True
        thread.start()
    
    def transpile_code(self, python_code):
        """PythonコードをGoコードに変換"""
        try:
            # Claude APIで変換
            prompt = f"""以下のPythonコードを、機能的に等価なGoコードに変換してください。

変換要件:
1. Pythonの機能をできるだけ忠実にGoで再現すること
2. Go言語の慣習に従った読みやすいコードにすること
3. 必要なimport文をすべて含めること
4. エラーハンドリングを適切に実装すること
5. コメントも翻訳して含めること
6. main関数を含む実行可能なコードにすること

Pythonコード:
```python
{python_code}
```

完全なGoコードのみを出力してください(説明文は不要)。"""

            message = self.client.messages.create(
                model="claude-sonnet-4-20250514",
                max_tokens=4000,
                messages=[
                    {"role": "user", "content": prompt}
                ]
            )
            
            go_code = message.content[0].text
            
            # コードブロックのマークダウンを削除
            if "```go" in go_code:
                go_code = go_code.split("```go")[1].split("```")[0].strip()
            elif "```" in go_code:
                go_code = go_code.split("```")[1].split("```")[0].strip()
            
            # UIスレッドで結果を表示
            self.root.after(0, self.display_result, go_code, None)
            
        except Exception as e:
            self.root.after(0, self.display_result, None, str(e))
    
    def display_result(self, go_code, error):
        """変換結果を表示"""
        # プログレスバーを停止
        self.progress.stop()
        self.transpile_btn.config(state=tk.NORMAL)
        
        if error:
            messagebox.showerror("エラー", f"変換エラー: {error}")
            self.update_status("変換失敗")
        else:
            self.go_text.delete("1.0", tk.END)
            self.go_text.insert("1.0", go_code)
            self.update_status("変換完了")
            messagebox.showinfo("成功", "Goコードへの変換が完了しました")


def main():
    root = tk.Tk()
    app = PythonToGoTranspiler(root)
    root.mainloop()


if __name__ == "__main__":
    main()