現在お買い物カゴには何も入っていません。
投稿者: akuroiwa
PywebviewでPythonとJavaScriptを連携:Promiseの役割と具体例
Pywebviewは、PythonとJavaScriptを連携させたデスクトップアプリケーション開発に役立つフレームワークです。しかし、Pythonプログラマーにとって慣れない「非同期処理」や「Promise」に直面することもあります。本記事では、py-chessboardjsを例に、以下を詳しく解説します:
- Promiseとは何か、なぜ必要か
- Pythonのメソッド戻り値をJavaScriptの関数に活用する方法
- 具体例:PGNファイルの読み込み
Promiseとは?
Promiseは、非同期処理の結果を待つためのオブジェクトであり、成功(
resolved
)または失敗(rejected
)の状態を持ちます。- Pythonでは、関数は通常即座に戻り値を返します(同期処理)。
- 一方、JavaScriptでは処理が非同期になることが多く、処理完了後に値を受け取る必要があります。
Pythonでは処理が終わるのを待って変数等に代入してくれますが、JavaScriptでは待ってくれません。
これを解決するために、PywebviewはPythonのメソッド呼び出し結果をPromiseでラップします。これにより、JavaScript側でthen
を使って結果を受け取れるようになります。
Pythonメソッドの戻り値をJavaScriptで利用する
以下は、py-chessboardjsのPGNファイル読み込み機能を使い、Pythonのメソッド結果をJavaScriptで処理する例です。
Python側のコード
PythonでPGNファイルを読み込み、その状態(FEN文字列)を返すメソッドを定義します:
class Api: def open_pgn_dialog(self): """ ユーザーにファイルダイアログを表示し、選択したPGNファイルを読み込み、 そのゲーム状態をFEN文字列で返す。 """ file_types = ('PGN File (*.pgn)', 'All files (*.*)') file_path = self.window.create_file_dialog(webview.OPEN_DIALOG, file_types=file_types)[0] if os.path.exists(file_path): self.pgn = open(file_path) self.load_games_from_file() return self.board.fen() # 現在のFEN文字列を返す return None
JavaScript側のコード
JavaScriptで、このPythonメソッドを呼び出し、結果(FEN文字列)を利用します:
function openPgnDialog() { // Python API を呼び出し pywebview.api.open_pgn_dialog().then(fen => { if (fen) { console.log('FEN文字列:', fen); // 必要に応じてフロントエンドで処理 updateBoardWithFen(fen); } else { console.error('PGNファイルの読み込みに失敗しました。'); } }).catch(error => { console.error('エラーが発生しました:', error); }); } // FEN文字列でボードを更新する例(仮) function updateBoardWithFen(fen) { alert('新しいFEN: ' + fen); }
ポイント:
pywebview.api.open_pgn_dialog()
はPromiseを返し、then
で結果を受け取り処理しています。
Promiseの基本的な使い方(Pythonプログラマー向け)
PromiseはPythonの「関数の戻り値」をJavaScriptの非同期処理に適応するための仕組みです。
- Pythonの戻り値はPromiseの成功状態(resolved value)として扱われます。
- JavaScriptでは、
then
を使って成功時の値を受け取ります。
Promiseの流れ
- Pythonメソッドが値を返す。
- PywebviewがPromiseに変換。
- JavaScriptで
then
を使い値を処理。
フロントエンドのUIデザイン:Bootstrapを活用
PywebviewはHTML/CSS/JavaScriptフレームワークを使用できるため、py-chessboardjsではBootstrapを活用し、ユーザーにとって使いやすいUIを構築しています。
実装例
以下は、
index.html
のナビゲーションバー部分です(省略のために一部改変):<nav class="navbar navbar-expand-sm navbar-dark bg-dark"> <div class="container-fluid"> <a class="navbar-brand" href="#">Py-Chessboardjs</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDarkDropdown" aria-controls="navbarNavDarkDropdown" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNavDarkDropdown"> <ul class="navbar-nav"> <li class="nav-item"><a class="nav-link" href="#">Home</a></li> <li class="nav-item"><a class="nav-link" href="#">Settings</a></li> </ul> </div> </div> </nav>
結果、レスポンシブなナビゲーションバーが表示され、簡単にカスタマイズできます。
まとめ
Promiseは、PythonとJavaScriptの動作の違いを吸収するために必要な仕組みです。今回の例では、py-chessboardjsを使いながら以下を学びました:
- PythonメソッドをJavaScriptから呼び出し、戻り値をPromiseで扱う方法。
- Bootstrapを利用したスタイリッシュなフロントエンドデザイン。
これらを応用すれば、直感的で高性能なアプリケーションを構築できます。
アロー関数を使う理由
今回、ChatGPTとClaudeに記事を書いてもらう際にpy-chessboardjsのコードを標準の書き方に修正してもらい、その理由を解説してもらいました。以下はその内容です。
JavaScriptの=>
はアロー関数(arrow function)を意味し、関数を簡潔に書くための記法です。従来のfunction
キーワードを使った関数定義と同じ動作をしますが、以下のような利点があります。-
簡潔な記法:
- 従来の
function
キーワードを省略できます。 -
例えば、以下のようなコードが簡略化されます:
// 通常の関数 function add(a, b) { return a + b; } // アロー関数 const add = (a, b) => a + b;
- 従来の
-
this
の挙動が直感的:-
アロー関数は親スコープの
this
をそのまま使用します。一方、従来のfunction
は呼び出し方によってthis
が変わるため、意図しない挙動を防げます。例:
function Example() { this.value = 42; // 通常の関数(意図した
this
ではない可能性あり) setTimeout(function() { console.log(this.value); // undefined(this
はグローバルを指す) }, 1000); // アロー関数(意図したthis
を保持) setTimeout(() => { console.log(this.value); // 42 }, 1000); } new Example();
-
-
Promiseチェーンでの一般的な書き方:
- Promiseチェーン(
then
やcatch
)内で、アロー関数を使うのが一般的です。 -
シンプルなコールバック処理に適しています:
// 通常の関数 pywebview.api.get_data().then(function(result) { console.log(result); }); // アロー関数 pywebview.api.get_data().then(result => { console.log(result); });
- Promiseチェーン(
アロー関数が好まれるケース
- 短い関数(関数リテラル): アロー関数は、数行で完結する関数リテラルに適しています。
- コールバック関数: 非同期処理(
setTimeout
やPromise
など)で使うと直感的です。
アロー関数を避けるべきケース
アロー関数は
this
の挙動が予測しにくいケースがあります。this
を明示的に保持する必要がある場合: メソッド内やイベントリスナーなど、this
の挙動が重要な場合は、従来の関数式を使用する方が安全です。-
this
の再定義が必要な場合: アロー関数ではthis
を新たに定義できません。そのため、例えばイベントリスナーの削除が必要な場合は避けるべきです。// イベントリスナーの登録 button.addEventListener('click', () => console.log('clicked')); // イベントリスナーの削除(動作しない) button.removeEventListener('click', () => console.log('clicked')); // 別の関数として扱われる
アロー関数は実際には
this
を明示的に保持するのに適していません。むしろ、アロー関数はthis
を現在のスコープから継承するため、メソッドやイベントリスナーでは注意が必要です。アロー関数は
this
の挙動が独特で、以下のような特徴があります:- アロー関数は、定義された場所の
this
コンテキストを継承します。 - 自身の
this
を持たず、外側のスコープのthis
をそのまま使用します。 - メソッドやイベントリスナーでは、通常の関数式の方が
this
の参照が明確です。
結論
=>
(アロー関数)を使った理由:
本記事ではPromiseチェーンでの一般的な記法を重視し、可読性と簡潔さのためにアロー関数を使用しました。特に短いコールバック関数を記述する場合、アロー関数が現代的で簡潔な書き方として推奨されるケースが多いです。
ただし、もし従来のfunction
キーワードに慣れている場合、どちらを使うかは個人のスタイルやプロジェクトのコーディング規約に依存します。JDIへの株主提案
以下は私が2024年11月19日にJDIへお問い合わせフォームを通して株主提案書を送信した内容です。実際に送信した内容は文字数制限のために文章の一部を削除してあります。
ジャパンディスプレイ株式会社 御中
株主提案書
ディスプレイの高付加価値化とモジュール化に関する提案
-
統合型ディスプレイモジュールの開発
小型ディスプレイに、プロセッサー、メインメモリー、記憶媒体を含む基盤を内蔵することで、付加価値を大幅に高めることを提案します。この統合により、以下の利点が期待できます:- 製品の差別化と競争力強化
- 顧客のデバイス設計簡素化によるコスト削減
- IoTデバイスやウェアラブル機器市場での新たな需要創出
-
RISC-Vアーキテクチャの採用
オープンソースのRISC-Vアーキテクチャを採用することで、以下のメリットが得られます:- カスタマイズ性の向上
- 開発コストの削減
- 省電力化と性能向上の両立
-
大日本印刷との技術提携強化
大日本印刷(DNP)の持つ先進技術を活用し、ディスプレイのモジュール化を推進します。
DNPの技術が本提案に寄与する点は以下の通りです:a. 印刷エレクトロニクス技術
DNPの印刷エレクトロニクス技術を用いることで、薄型・軽量・フレキシブルな電子回路の形成が可能となります。
DNPのナノインプリント技術により、ディスプレイへの回路内蔵が容易になり、モジュール化を効率的に進められます1。b. 光学フィルム技術
DNPの高機能光学フィルム技術を活用することで、ディスプレイの視認性向上が可能となります。
これは、統合型モジュールの性能向上に直結します2。c. メタバース関連技術
DNPが開発中のメタバース技術を活用することで、統合型ディスプレイモジュールに新たな付加価値を付与できる可能性があります。
例えば、XRコミュニケーション技術を組み込むことで、より没入感の高い表示が可能になります3。d. デジタルアーカイブ技術
DNPのデジタルアーカイブ技術を応用することで、統合型ディスプレイモジュールにコンテンツ管理機能を付加し、
より高度な情報表示システムを構築できます4。 -
新市場戦略
開発した統合型ディスプレイモジュールを、スマートフォン、スマートウォッチ、ヘッドマウントディスプレイのメーカーに積極的に提案し、採用を促進します。
これらの施策により、ジャパンディスプレイの小型ディスプレイ事業の競争力を飛躍的に高め、新たな成長機会を創出できると考えます。大日本印刷との技術提携を通じて、印刷技術とエレクトロニクス技術の融合による革新的な製品開発が可能となり、市場での優位性を確立できるものと確信しております。
-
Self-Debuggingの先駆け:bolt.new
bolt.newは、AIを活用した革新的なWeb開発プラットフォームです。自然言語での指示だけで、フルスタックのWebアプリケーションを簡単に作成できる画期的なツールとして注目を集めています。
AIが生み出す驚異のシミュレーション:bolt.newの実力
最新のAI駆動型Web開発プラットフォーム、bolt.newの驚くべき能力をご紹介します。私自身がbolt.newを使って作成したシミュレーション「Kinzhal Busters」をご覧ください。このプロジェクトは、現代の軍事技術と防衛システムを模したインタラクティブな3Dシミュレーションです。
Kinzhal Busters: https://github.com/akuroiwa/kinzhal-busters
このシミュレーションでは、発電所に飛来するKinzhal(キンジャール)ミサイルと、それを迎撃しようとする複数のドローンによる防衛システムの動きを再現しています。Three.jsを駆使した立体的な表現により、複雑な軌道や迎撃のプロセスを視覚的に理解しやすい形で表現しています。
bolt.newの驚異的な点は、このような高度な3Dシミュレーションを、プログラミングの詳細な知識がなくても、自然言語での指示だけで作成できることです。AIが要求を理解し、適切なライブラリやフレームワークを選択し、必要なコードを生成してくれるのです。
Self-Debugging: エラー解決の新たなアプローチ
bolt.newの特筆すべき機能の一つが、Self-Debuggingです。開発中に発生したエラーを、AIが自動的に解析し修正案を提示します。「Fix problem」ボタンをクリックするだけで、AIがエラーを修正し、アプリケーションを正常に動作させることができます。
Self-Debuggingについては、論文Teaching Large Language Models to Self-Debugを参照してください。これは、これからのコード生成サービスで主流になる可能性が高い機能です。
Viteとパッケージのインストール
bolt.newでプロジェクトを作成すると、デフォルトでViteが選択されます。Viteは高速な開発サーバーと最適化されたビルドツールを提供する次世代のフロントエンドツールです。
ノーコードで全てが完結する訳ではありません。Stackblitzならば自前でインストールせずともWebブラウザで確認できますが、お気に入りのエディタでコードを手直しし、気軽に動作確認したいでしょう。ここでは、その方法を説明します。
Ubuntuでの必要なパッケージのインストール
- Node.jsとnpm:
sudo apt update sudo apt install nodejs npm
- 必要に応じてNode.jsのバージョンを更新:
sudo npm install -g n sudo n stable hash -r npm -v node -v
npmでインストールする必要があるもの
プロジェクトのルートディレクトリで以下のコマンドを実行します:
npm install
これにより、
package.json
に記載されている全ての依存関係がインストールされます。また、bolt.newで生成されるプロジェクトの.gitignoreファイルには、通常
components/
ディレクトリが含まれ、バージョン管理から除外されます。Viteプロジェクトの起動
- 開発サーバーの起動:
npm run dev
これにより、開発用のサーバーが起動し、通常はhttp://localhost:5173でアプリケーションにアクセスできます。
h
を入力しenter
を押せば、使い方を表示してくれます。- プロダクションビルド:
npm run build
これにより、プロダクション用のビルドが作成されます。
- プロダクションビルドのプレビュー:
npm run preview
ビルドされたプロダクションバージョンをローカルでプレビューできます。
StackBlitzとGitHub連携
StackBlitzは、GitHubリポジトリとの連携機能を提供しています。
bolt.newに作成してもらったプロジェクトをGitHubリポジトリとして登録できます。
プロジェクトの動作確認も出来るので、Webブラウザさえあれば、いつでも作業できます。StackblitzもNetlifyも、bolt.newと同じくGitHubアカウントでアカウント登録したりサインインしたりできます。
bolt.newからNetlifyへのデプロイとユーザー権限移譲
bolt.newで作成したプロジェクトをNetlifyにデプロイした直後に表示される「claim URL」をクリックすることで、
アプリケーションの所有権があなたのNetlifyアカウントに移行されます。
この過程で、デプロイ時に表示されたURLを控えておくことが重要です。新しい所有者がプロジェクトにアクセスする際に必要となります。また、GitHubで更新し、Netlifyのアプリも更新したい場合にはリポジトリの登録が必要です。
bolt.newは、AIの力を借りてWeb開発のプロセスを大幅に簡素化し、効率化する革新的なツールです。プログラミングの経験が浅い方でも、複雑なWebアプリケーションを作成できる可能性を秘めています。
「上祖師谷三丁目一家4人強盗殺人事件」の考察
「上祖師谷三丁目一家4人強盗殺人事件」、所謂「世田谷一家殺害事件」が発生したのは2000年ですが、これを連続殺人事件と仮定すると以下のようになります。因みに、この記事の内容は既に警視庁に情報提供済みです。前半は送信した電子メールの内容で、後半のGoogle マップは今回加筆したものです。
「上祖師谷三丁目一家4人強盗殺人事件」連続殺人の可能性について
特別捜査本部の関係者様
何度も電子メールを送りまして御迷惑かも知れませんので、これで一旦最後とします。
どうか最後まで読んで下さい。この事件の発生する数年間に世田谷区内で4件の未解決事件の殺人事件が発生していることを前回指摘しました。
Wikipedia「未解決事件」より抜粋:
- 1997年11月20日 ‐ 世田谷区八幡山三丁目アパート殺人事件
- 1998年4月8日 ‐ 世田谷区新町2丁目男性殺人事件
- 1999年7月12日 ‐ 世田谷区新町二丁目新築工事現場内女性殺人事件
- 2000年12月30日 – 世田谷一家殺害事件
これらの特徴として以下の2点が挙げられます:
- 犯人の目撃情報がない、若しくは少ない
- 防犯カメラ映像がない
以上の点から導き出した私なりの結論です:
- 犯人は殺害現場まで徒歩で移動した
- 周辺の地理や人通りに詳しい
- 防犯カメラの位置を熟知している
私が想像する犯人像です。これらの内のいずれかに該当する者でしょう:
- 小田急電鉄小田原線の千歳船橋駅を中心とした徒歩圏内で生活できる住宅地に住む者
- 地元出身者、若しくは居住者
- 勤務地がある者
Google マップ
徒歩での所要時間をクリックして下さい。Google マップへのリンクです。因みに、自転車や路線バスを利用すれば移動時間はより短縮されます。
1997年11月20日:世田谷区八幡山三丁目アパート殺人事件
Emacs入門
Emacsの基本と開発
チュートリアルの起動
Emacsを起動後、以下のコマンドでチュートリアルを開始できます:
C-h t
日本語版を起動するには:
C-h t japanese
これを練習しないと、例えばマニュアルでのキーバインドの特殊な記法の意味すら理解できません。上記のキーバインドの意味が分からない方は、プルダウンのHelpメニューから辿って下さい。時間はかかりません。すぐに終わります。
基本的な使い方
- 起動と終了:
- 起動:ターミナルで
emacs
と入力 - コマンドラインでの使用:
emacs -nw
と入力 - 終了:
C-x C-c
- 起動:ターミナルで
- 基本的なカーソル移動:
- 前後左右:
C-p
,C-n
,C-b
,C-f
- 行頭/行末:
C-a
,C-e
- 前後左右:
- ファイル操作:
- 開く:
C-x C-f
- 保存:
C-x C-s
- 開く:
- 編集:
- コピー:
M-w
- カット:
C-w
- ペースト:
C-y
- コピー:
- バッファ操作:
- バッファ切り替え:
C-x b
- バッファ一覧:
C-x C-b
- バッファ切り替え:
Elispでの開発方法
- Elispファイルの作成:
.el
拡張子のファイルを作成 - 基本的な構文:
(defun my-function (arg) "Documentation string." (interactive "p") (message "Hello, %s" arg))
- 評価:
- 関数全体:カーソルを関数定義の末尾に置き
C-x C-e
- バッファ全体:
M-x eval-buffer
- 関数全体:カーソルを関数定義の末尾に置き
- デバッグ:
- デバッガの有効化:
(setq debug-on-error t)
- ブレークポイントの設定:
(debug)
- Flycheckによるsyntaxチェック
- デバッガの有効化:
- パッケージ開発:
provide
を使用してパッケージ名を定義- 依存関係は
require
で指定
極端な話、M-x load-file RETとC-h fとC-h vを知っていれば、ある程度までは試行錯誤で出来ます。まずは Programming in Emacs Lisp を読みましょう。
load-path
とload
の違いload-path
は、Emacsがライブラリを検索するディレクトリのリストです。新しいディレクトリを追加するには、add-to-list
関数を使います。;; ~/.emacs.d/init.el に記述 (add-to-list 'load-path "~/.emacs.d/site-lisp/")
これにより、
~/.emacs.d/site-lisp/
ディレクトリ内のファイルがEmacsの検索対象に追加されます。load
関数は指定したファイルをロードします。ファイルの拡張子(通常は.el
)は省略可能です。;; ~/.emacs.d/init.el に上記設定に続いて記述 ;; ~/.emacs.d/site-lisp/my-settings.el (load "my-settings")
これにより、
~/.emacs.d/site-lisp/my-settings.el
がロードされます。require
関数は指定したライブラリがロードされていなければロードします。provide
関数とセットで使用されることが多いです。flycheckを有効にしていると、elispファイルの末尾で
provide
を書けと注意されるので、flycheck-copy-errors-as-kill
でコピーすると便利です。;; ~/.emacs.d/site-lisp/my-settings.el に記述 (provide 'my-settings) ;;; my-settings.el ends here ;; ~/.emacs.d/init.el に記述 ;; load-pathが通っていることが前提 (require 'my-settings)
設定ファイルを幾つも書いていて、まとめて
load
する必要がある場合、EmacsWikiに投稿されているload-directoryを利用すると便利です。但し、load-directory.elは別のディレクトリに置いた方が良いかも知れません。以下の設定で、そのファイルを2度load
するからです。;; load-pathが通っていることが前提 (load "load-directory") ;; 或いは (load "~/.emacs.d/site-lisp/load-directory") ;; provideが書かれていれば (require 'load-directory) (load-directory "~/.emacs.d/site-lisp")
以下の関数はload-directoryを元にChatGPTが書いてくれました。
load
ではなく、require
を再帰的に実行します。(defun require-directory (directory)
"Require recursively all `.el' files in DIRECTORY."
(dolist (element (directory-files-and-attributes directory nil nil nil))
(let* ((path (car element))
(fullpath (concat directory "/" path))
(isdir (car (cdr element)))
(ignore-dir (or (string= path ".") (string= path ".."))))
(cond
((and (eq isdir t) (not ignore-dir))
(require-directory fullpath))
((and (eq isdir nil) (string= (substring path -3) ".el"))
(require (intern (file-name-sans-extension path))))))))以下は~/.emacs.d/init.elの設定です。
;; load-pathが通っていることが前提 ;; load-directoryと同じファイル名と仮定 ;; ~/.emacs.d/site-lisp/load-directory.el (load "load-directory") ;; provideが書かれていれば (require 'load-directory) (require-directory "~/.emacs.d/site-lisp")
MELPA (Milkypostman’s Emacs Lisp Package Archive)
MELPAは、Emacsの人気のあるパッケージリポジトリです。開発したパッケージを登録することも出来ます。プルリクエストとしてRecipeを提出する方法はREADMEを御覧ください。Pull requestsタブをクリックして書き方の参考にすると良いでしょう。
- MELPAの設定:
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize)
- パッケージのインストール:
M-x package-install RET package-name RET
- パッケージの更新:
M-x package-list-packages RET U x
keyword-searchプロジェクト
keyword-searchは、Emacsでブラウザスタイルのキーワード検索を可能にするパッケージです。
- インストール:
M-x package-install RET keyword-search RET
- 基本的な使用方法:
M-x keyword-search RET
- 検索エンジンを選択(TABで補完可能)
- 検索クエリを入力
- カスタマイズ:
- デフォルト検索エンジンの設定:
M-x customize-variable RET keyword-search-default RET
- 検索エンジンの追加:
M-x customize-variable RET keyword-search-alist RET
- デフォルト検索エンジンの設定:
- 拡張モード:
- 追加の言語サービス:
keyword-search-extra-mode
- マニア向けウェブサイト:
keyword-search-mad-mode
- 追加の言語サービス:
keyword-searchは、Emacsユーザーが効率的にウェブ検索を行えるようにする便利なツールです。MELPAを通じて簡単にインストールでき、カスタマイズも容易です。
browse-apropos-urlを元にMr. Jens Petersenが開発しました。私が書いたコードよりずっと素晴らしいです。私はプルリクエストを提出したことがきっかけで開発に参加しました。2024年現在、最後のコミットが6年前なので、動作しないURLや機能があるでしょうが、検索に役立つので是非試してください。
プログラミングの作業の大半は調べものなのですから。
Emacsでの定義元ジャンプと自動補完の設定
定義元ジャンプ
定義元ジャンプには、主に以下のパッケージが使用されます:
xref
: Emacsに標準搭載されているパッケージdumb-jump
: 外部ツールに依存しない汎用的なジャンプツール
xrefの設定
M-.
がxref-find-definitions
に、M-,
がxref-go-back
に割り当てられています。xref-pop-marker-stack
はEmacs 29.1で廃止されました。C-h k M-.
でキーバインドを確認できます。設定されていなければ、以下のように設定し直すことが出来ます。(global-set-key (kbd "M-.") 'xref-find-definitions) (global-set-key (kbd "M-,") 'xref-go-back)
xref
を使う前に、TAGS
ファイルを作成する必要があります。以下のコマンドを使用してTAGS
ファイルを生成します。Pythonでの例:
etags --help --lang=python In Python code, 'def' or 'class' at the beginning of a line generate a tag. find . -type f -name "*.py" -exec etags -a {} + find /usr/lib/python3/dist-packages/ -type f -name "*.py" -exec etags -a {} +
ctagsやetagsの拡張がaptでインストール出来ます。例えば:
sudo apt install universal-ctags ls -l /usr/bin/etags lrwxrwxrwx 1 root root 23 3月 16 2023 /usr/bin/etags -> /etc/alternatives/etags* ls -l /etc/alternatives/etags lrwxrwxrwx 1 root root 24 7月 16 22:10 /etc/alternatives/etags -> /usr/bin/ctags-universal*
dumb-jumpの設定
MELPAからインストール:
M-x package-install RET dumb-jump RET
設定。xrefの上書き:
(require 'dumb-jump) (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
自動補完
自動補完には、
company-mode
を使用します。MELPAからインストール:
M-x package-install RET company RET
設定:
(add-hook 'after-init-hook 'global-company-mode)
MELPAでインストールすべき便利なパッケージ
選択候補を表示した方が早いこともあります。例えば、yank-popを視覚化したcounsel-yank-popの方が使いやすいと多くの人が感じるでしょう。私も思います。
ivy
1: 補完フレームワークM-x package-install RET ivy RET
counsel
2: ivyを使用した各種コマンドの強化版M-x package-install RET counsel RET
swiper
: ivyを使用した検索機能M-x package-install RET swiper RET
projectile
: プロジェクト管理ツールM-x package-install RET projectile RET
magit
: GitクライアントM-x package-install RET magit RET
flycheck
: シンタックスチェッカーM-x package-install RET flycheck RET
flycheckの説明と設定
flycheckは、コードの文法チェックをリアルタイムで行うツールです。多くのプログラミング言語に対応しています。
お薦めの関数は
flycheck-copy-errors-as-kill
です。その場のエラーをkill ringにコピーできるので、そのままyank出来ます。因みに、この記事ではbuilt-inのFlymakeやEglotの説明をしません。
設定:
(add-hook 'after-init-hook #'global-flycheck-mode)
global-flycheck-mode
はあらゆる場面で起動するため、特定のメジャーモードでのみ起動する設定を推奨します。(add-hook 'emacs-lisp-mode-hook 'flycheck-mode) (add-hook 'python-mode-hook 'flycheck-mode)
Pythonの場合、Flycheck は python-flake8 または python-pylint を使用して Python をチェックし、どちらも使用できない場合は python-pycompile を使用します(fall back)。
Supported Languagespip install pylint
lsp-modeの設定とlanguage serverのインストール
lsp-modeのインストールと設定
MELPAからインストール:
M-x package-install RET lsp-mode RET
設定例:
(require 'lsp-mode) (add-hook 'python-mode-hook #'lsp) (add-hook 'c-mode-hook #'lsp) (add-hook 'javascript-mode-hook #'lsp) (add-hook 'prog-mode-hook #'lsp) ;; あらゆるprogramming modesで起動
後者の設定は
prog-mode
3より派生するmajor modesに対応できるので便利です。Language Serverのインストール方法
一つのプログラミング言語に対応する複数のlanguage serverがあります。
- Python (pyright)
npm install -g pyright which pyright /home/foo/.npm-global/bin/pyright
- Python(jedi-language-server)
pip install -U jedi-language-server
- C/C++ (clangd)
sudo apt install clangd
- JavaScript (typescript-language-server)
npm install -g typescript-language-server
- Objective-C (clangd)
sudo apt install clangd
lsp
の切り替えC-u M-x lsp
つまり数引数を先に与えてlsp
を実行すると、language serverを切り替えることが出来ます。例えばPythonで複数のlanguage serverをインストールしている場合に便利です。lsp-pyrightのインストールと設定はREADMEに書かれています。
使用しているvenvを指定するには
C-h lsp-pyright-venv-path
でcustomize this variableのリンクに入ります:/home/foo/.venv3.12 ;; 初期値はnil
lsp-jediのインストールと設定もREADMEに書かれています。venvのpipでjedi-language-serverをインストールすると、lspが呼び出せませんので以下の作業が必要になります。また、Emacsで使用する前に毎回activateする必要があります。
まず、コマンドのパスを調べます:
source ~/.venv3.12/bin/activate # venvの例 which jedi-language-server
C-h v lsp-jedi-executable-commandでcustomize this variableのリンクに入ります:
jedi-language-server ;; 変更前の初期値 /home/foo/.venv3.12/bin/jedi-language-server ;; 変更例
Jediを使った他の補完方法
lsp-jediを使わずcompany-jediを使う方法もあります。
MELPAからインストール:
M-x package-install RET company-jedi RET
設定:
(defun my/python-mode-hook () (add-to-list 'company-backends 'company-jedi)) (add-hook 'python-mode-hook 'my/python-mode-hook)
auto-completeとjedi.el(MELPAパッケージ名はjedi)を使う方法もあります。但し、virtualenvに依存します。aptやpipでのインストールが必要です。現在はvenvが主流ですので勘違いしないで下さい。両者は別物です。詳しくはマニュアルを参照して下さい。
以下の作業も必要になるでしょう:
M-x jedi:install-server RET M-x jedi:reinstall-server RET ;; 2回目から
~/.emacs.d/.python-environments/default/
に仮想環境が作られます。デバッグの設定と使い方
デバッグの設定と使い方についても簡単に説明します。
- Emacs標準のgud-modeを使用する場合:
M-x gdb M-x pdb ;; Pythonの場合
pdbの場合、ミニバッファに以下のように表示されるのでファイルを指定します:
Run pdb (like this): python -m pdb myscript.py
キー割り当て
キーボードに右Altが無いと、Emacsユーザーには不便です。以下のように設定すると、変換キーをEscのように使うことが出来ます。
;; 「無変換」キーで定義の先頭に移動 (global-set-key [muhenkan] 'beginning-of-defun) ;; MetaつまりAltを押しながら「無変換」で定義の末尾に移動 (global-set-key (kbd "M-<muhenkan>") 'end-of-defun) ;; 「変換」キーをEscのようにする (global-set-key (kbd "<henkan>") esc-map) ;; 「カタカナひらがな」キーをM-xにする (global-set-key [hiragana-katakana] 'execute-extended-command)
まとめ
設定したりパッケージを導入することで、Emacsの機能を大幅に拡張し、より効率的な開発環境を構築することができます。定義元ジャンプや自動補完、シンタックスチェックなどの機能は、コーディングの生産性を大きく向上させます。
Emacsのパッケージとは別に、aptやpipやnpmでインストールしてEmacsから呼び出すものがあるので混乱するかも知れませんが、そのソフトウェアの開発言語が何かを知っていれば、何故そのpackage managerでインストールするのか理解できるでしょう。
Citations:
[1] keyword-search.el
[2] Emacsの特徴や活用方法を徹底解説!
[3] Emacsチュートリアル 日本語訳
[4] emacs の使い方
[5] Emacs の簡単な使い方
[6] #17 “手遅れ”を防ぐ Emacsのセーフガードシステム (Software Design 2015年9月号掲載記事) Emacs undo redo 使い方
[7] 突然だがEmacs を始めよう
[8] Programming in Emacs Lisp
[9] EmacsでFlycheckのウィンドウをトグルできるようにした
[10] ctagとetagについて #8
[11] exuberant-ctagsとuniversal-ctagsの違い
[12] Flycheck を Python で使うためにしたことメモ
[13] Flycheck — Syntax checking for GNU Emacs- 起動と終了:
GNU nano
GNU nanoテキストエディタの基本的な使い方
GNU nanoは、Linuxシステムで広く使用されている、シンプルで使いやすいコマンドラインテキストエディタです。以下に、nanoの基本的な使い方を説明します。
1. nanoの起動
ターミナルで以下のコマンドを入力してnanoを起動します:
nano
特定のファイルを開く場合は、ファイル名を指定します:
nano ファイル名
2. 基本的な編集
- テキストの入力:カーソル位置に直接入力します。
- カーソル移動:矢印キーを使用します。
- 行の先頭/末尾に移動:Ctrl+A / Ctrl+E
- ページ上下:Ctrl+Y / Ctrl+V
3. テキストの操作
- 切り取り(カット):Ctrl+K
- 貼り付け(ペースト):Ctrl+U
- コピー:Alt+6でマーク開始、移動後Alt+6で範囲指定、Alt+6でコピー
4. 検索と置換
- 検索:Ctrl+W
- 次を検索:Alt+W
- 置換:Ctrl+\
5. ファイルの保存と終了
- 保存:Ctrl+O
- 終了:Ctrl+X(変更がある場合は保存するか尋ねられます)
6. その他の便利な機能
- ヘルプ表示:Ctrl+G
- 行番号表示切替:Alt+N
- スペルチェック(要aspell):Ctrl+T
7. nanoの設定
~/.nanorc ファイルを編集することで、nanoの動作をカスタマイズできます。例:
set autoindent set tabsize 4 set linenumbers
nanoは直感的で学習曲線が緩やかなため、初心者にも扱いやすいエディタです。これらの基本的なコマンドを覚えれば、多くの編集作業をスムーズに行うことができます。より高度な機能については、nanoのマニュアル(man nano)を参照してください。
Citations:
[1] nano Command Manual
[2] GNU nano
[3] Nano
[4] A Beginner’s Guide to Using the GNU nano Text Editor on LinuxPythonパッケージをソースからインストールする
Gitリポジトリからのpythonパッケージインストール方法
GitHubやその他のバージョン管理システム(VCS)のリポジトリから直接Pythonパッケージをインストールすることができます。これは、まだPyPIに公開されていないパッケージや、最新の開発バージョンを使用したい場合に特に便利です。
Gitリポジトリからpythonパッケージをインストールする方法には、主に2つのアプローチがあります:リモートリポジトリから直接インストールする方法と、ローカルにクローンしたリポジトリからインストールする方法です。
リモートリポジトリから直接インストール
基本的な使用方法
pip install git+https://github.com/username/repository.git
具体的な例
- 公開リポジトリからのインストール:
pip install git+https://github.com/numpy/numpy.git
- 特定のブランチやタグからインストール:
pip install git+https://github.com/username/repository.git@branch-name pip install git+https://github.com/username/repository.git@v1.0
- サブディレクトリにあるパッケージのインストール:
pip install git+https://github.com/username/repository.git#subdirectory=package_dir
プライベートリポジトリからのインストール
プライベートリポジトリからインストールする場合、認証が必要です。
- HTTPSを使用する場合:
pip install git+https://username:password@github.com/username/repository.git
注意: パスワードをコマンドラインに直接入力することは推奨されません。代わりに、個人アクセストークンを使用することをお勧めします。
- SSHを使用する場合:
pip install git+ssh://git@github.com/username/repository.git
SSHキーの設定が必要です。
requirements.txtでの使用
requirements.txt
ファイルでGitHubリポジトリを指定することもできます:git+https://github.com/username/repository.git@v1.0
ローカルにクローンしたリポジトリからインストール
このアプローチは、リポジトリをローカルマシンにクローンし、そのディレクトリに移動してインストールする方法です。
手順
- リポジトリをクローン:
git clone https://github.com/username/repository.git
- クローンしたディレクトリに移動:
cd repository
- パッケージをインストール:
pip install .
具体的な例
git clone https://github.com/username/my-project.git cd my-project pip install .
開発モードでのインストール
パッケージを開発中で、ソースコードを編集しながらテストしたい場合は、開発モードでインストールすることができます:
pip install -e .
-e
オプション(または--editable
)を使用すると、パッケージがソースディレクトリにリンクされ、ソースコードの変更がすぐに反映されます。注意点
- どちらの方法でも、リポジトリには
setup.py
またはpyproject.toml
ファイルが含まれている必要があります。 - ローカルにクローンする方法は、パッケージのソースコードを確認したり、修正を加えたりする場合に特に便利です。
- 開発モードでのインストールは、自作のパッケージを開発する際に非常に有用です。
- セキュリティ上の理由から、信頼できるソースからのみインストールしてください。
- 依存関係の管理に注意が必要です。特に、複数のプロジェクトで作業している場合は、仮想環境の使用を検討してください。
まとめ
GitリポジトリからPythonパッケージをインストールする方法は、開発中のパッケージや、まだPyPIに公開されていないパッケージを使用する際に非常に便利です。リモートからの直接インストールとローカルにクローンしてからのインストールの両方の方法を理解しておくことで、様々な状況に対応できます。
Citations:
[1] Python のビルドとテスト
[2] Python配布パッケージをGitHubリポジトリ経由でインストールする方法(PublicとPrivate両パターン)
[3] setup.pyのないGitHubリポジトリからライブラリをimportする方法
[4] GitHub のプライベートリポジトリから Python の独自パッケージをインストールしてみた
[5] 【Python】GitHubから直接パッケージをインストールする方法
[6] GitHub のリポジトリを requirements.txt に含めるPython 3.12でのパッケージング手法の変更
Python 3.12におけるパッケージングの変更と pandas_datareader のインストール問題
Python 3.12では、パッケージングシステムに大きな変更が加えられました。これにより、一部のライブラリのインストールに影響が出ています。特に pandas_datareader のインストール時に遭遇する可能性のあるエラーと、その解決方法について説明します。
pandas_datareader のインストール問題
Python 3.12で pandas_datareader をインストールしようとすると、以下のようなエラーが発生する可能性があります:
ModuleNotFoundError: No module named 'distutils'
このエラーは、Python 3.12で setuptools が必要になったことが原因です。setuptools は以前は distutils モジュールに依存していましたが、Python 3.12ではこのモジュールが削除されました1。
解決方法
この問題を解決するには、以下の手順を試してください:
- setuptools を最新版にアップグレードする:
pip install --upgrade setuptools
- pandas_datareader をインストールする:
pip install pandas_datareader
Numpy のビルドシステム変更
Python 3.12では、Numpy のようなライブラリでもビルドシステムの変更が行われています。Numpy は Python 3.12 でデフォルトのビルドシステムを meson build system に移行しました2。これにより、setuptools の使用は非推奨となり、将来的には廃止される予定です。
pyproject.toml の推奨
パッケージングで pyproject.toml が強く推奨されている理由の一つは、このようなビルドシステムの変更に対応するためです。pyproject.toml を使用することで、プロジェクトのビルドシステムやその依存関係を明確に指定できます。
以下は pyproject.toml の簡単な例です:
[build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "example_project" version = "0.1.0" description = "An example project" dependencies = [ "pandas", "numpy", ] [project.scripts] my-script = "example_project.cli:main"
console_scripts と名前空間
pyproject.toml の
[project.scripts]
セクション(または setup.py の entry_points)で指定される console_scripts は、モジュールパスとコロンで区切られた関数名を使用します。例えば、
example_project.cli:main
はexample_project/cli.py
ファイル内のmain()
関数を指しています。この指定方法はクラス定義内のメソッドにも適用できます。例えば:
class CLI: @staticmethod def main(): print("Hello from CLI!")
この場合、pyproject.toml では以下のように指定できます:
[project.scripts] my-script = "example_project.cli:CLI.main"
Pythonのパッケージの作成と登録
setup.pyとpyproject.tomlの関係
setup.pyとpyproject.tomlの役割
setup.py
は長い間、Pythonパッケージのビルドと配布のための標準的な設定ファイルとして使用されてきました。しかし、近年ではpyproject.toml
が推奨されています。pyproject.toml
は、パッケージングツールやその他のツールの設定を一元管理するためのファイルです。pyproject.tomlの利点
-
ツールの統一:
pyproject.toml
は、ビルドシステムの依存関係やプロジェクトのメタデータを一つのファイルにまとめることができます。これにより、プロジェクトの設定が一元化され、管理が容易になります。 -
ビルドシステムの宣言:
[build-system]
テーブルを使用して、プロジェクトのビルドに必要なツールや依存関係を明示的に宣言できます。これにより、ビルド環境の再現性が向上します。 -
ツール間の互換性:
pyproject.toml
は、setuptools
、poetry
、flit
などの異なるビルドツールと互換性があります。これにより、特定のツールに依存せずにプロジェクトを管理できます。
setup.pyは不要か?
新しいプロジェクトでは、
pyproject.toml
を使用することが強く推奨されています。特に、ビルド中にカスタムスクリプトを実行する必要がない場合、setup.py
は最小限のスタブとしてのみ使用されるべきです。具体的には、以下のように最小限のsetup.py
を使用できます:# setup.py import setuptools setuptools.setup()
具体的な設定例
以下に、
pyproject.toml
の具体的な設定例を示します:[build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [project] name = "your-package-name" version = "0.1.0" description = "A short description of your package" authors = [ { name = "Your Name", email = "your.email@example.com" } ] dependencies = [ "requests >= 2.0.0", "numpy >= 1.18.0" ] [tool.black] line-length = 88
PyPIへのパッケージ登録手順
-
TestPyPIでのテスト:
- TestPyPIにアカウントを作成し、APIトークンを取得します。
- パッケージをビルドし、TestPyPIにアップロードしてテストします。
-
APIトークンの取得:
- PyPI(またはTestPyPI)のアカウント設定からAPIトークンを生成します。
-
.pypircファイルの設定:
- ホームディレクトリに
.pypirc
ファイルを作成し、以下のように設定します:
- ホームディレクトリに
[distutils] index-servers = pypi testpypi [pypi] username = __token__ password = <Your-PyPI-API-token> [testpypi] username = __token__ password = <Your-TestPyPI-API-token>
- パッケージのビルドとアップロード:
python -m build
コマンドでパッケージをビルドします。python -m twine upload --repository testpypi dist/*
でTestPyPIにアップロードします。- テストが成功したら、
python -m twine upload dist/*
で本番のPyPIにアップロードします。
まとめ
最新の情報では、
pyproject.toml
が推奨されています。特に新しいプロジェクトでは、pyproject.toml
を使用することで、設定の一元管理やビルド環境の再現性が向上します。setup.py
は最小限のスタブとして使用し、主要な設定はpyproject.toml
に記述することが推奨されます。Citations:
[1] Pythonで自作ライブラリを作るとき、setup.pyに代えてpyproject.tomlを使ってみませんか?
[2] pyproject.toml を書く
[3] Should pyproject.toml configs always be required to use poetry? #3443
[4] Should I be using only pyproject.toml? [closed]
[5] pyproject.toml specification-
Pythonの仮想環境(venv)とパッケージ管理(pip)の基本
1. 仮想環境(venv)とは
仮想環境は、プロジェクトごとに独立したPython環境を作成するためのツールです。これにより、異なるプロジェクトで異なるバージョンのパッケージを使用することができます。
2. 仮想環境の作成と使用
仮想環境の作成
# プロジェクトディレクトリに移動 cd my_project # 仮想環境の作成 python3 -m venv venv
仮想環境の有効化
# Unix/macOS source venv/bin/activate # Windows venv\Scripts\activate
仮想環境の無効化
deactivate
3. パッケージ管理(pip)
pipの基本
pipはPythonのパッケージ管理ツールで、パッケージのインストール、アップグレード、アンインストールを行います。
パッケージのインストール
pip install package_name
パッケージのアップグレード
pip install --upgrade package_name
パッケージのアンインストール
pip uninstall package_name
インストール済みパッケージの一覧表示
pip list
パッケージの詳細情報
pip show package_name
4. requirements.txtの使用
requirements.txtの作成
プロジェクトで使用しているパッケージを一覧にして、他の開発者が同じ環境を再現できるようにします。
pip freeze > requirements.txt
requirements.txtからパッケージをインストール
pip install -r requirements.txt
5. パッケージの作成と配布
パッケージの構成
以下では従来の方法を説明します。強く推奨されている
pyproject.toml
については1別の機会に説明します。パッケージを作成するためには、以下のようなディレクトリ構造が必要です:
my_package/ ├── my_package/ │ ├── __init__.py │ └── module.py ├── setup.py └── README.md
setup.pyの例
通常、ソフトウェアの開発はパッケージのビルドを前提としているファイルとパスの構成になっていますので、GitHub等で参考となるプロジェクトの書き方を手本とするのが早道です。参考になるかどうかはわかりませんが、私の管理するプロジェクトのレポジトリはこちらです。
console_scripts
は、例えばLinuxならばシェルコマンドとして動作します。仮想環境が~/.venv3.12
ならば、~/.venv3.12/bin/
以下にインストールされます。コマンドとして呼び出したい関数を指定します2。from setuptools import setup, find_packages setup( name='my_package', version='0.1', packages=find_packages(), install_requires=[ 'requests', ], entry_points={ 'console_scripts': [ 'my_command=my_package.module:main', ], }, )
パッケージのビルドと配布
Pythonパッケージユーザーガイド(Python Packaging User Guide)をまず読みましょう。以下のコマンドでは非推奨となった方法も併記します3。
# パッケージのビルド(非推奨となった。旧式) python setup.py sdist bdist_wheel # 推奨 python -m build # PyPIにアップロードするためのツールをインストール pip install twine # パッケージのアップロード twine upload dist/*
6. Gitと仮想環境の管理
.gitignoreの設定
仮想環境のディレクトリをGitの管理対象から除外するために、.gitignoreファイルに以下を追加します。GitHubからコピーしてくると良いでしょう4:
venv/
まとめ
この記事では、Pythonの仮想環境(venv)とパッケージ管理(pip)の基本的な使用方法について説明しました。仮想環境を使用することで、プロジェクトごとに独立した環境を作成し、依存関係の管理が容易になります。また、pipを使用してパッケージのインストールや管理を行うことで、開発効率を向上させることができます。さらに、requirements.txtを使用して環境を再現可能にし、setup.pyを使用してパッケージを作成・配布する方法も紹介しました。