非常に初期段階のAnki
のプラグイン作成テストをやっていく。
最も重要なことはAnki
はPython
で書かれているということだ。必然的に私もPython
を書くこととなる。
Python
は苦手なので細かいところから見ていこうと思う。
もし需要がありそうであればシリーズが継続するかもしれない。
直接データベースにカードを挿入したい
Anki
のカード作成機能は十分な機能を備えているが、プログラムを使って半自動でカードを作って入れていくためには自前の開発が必要になる。
つまりAnki
のカード追加画面を起動せずとも、自前のUIからカードを半自動で生成してDBに登録するものを作りたい。
Anki
では「アドオン」としてAnki
本体のメニューから起動できる物がある。
例えばオーディオの再生に一時停止などをもたせたり、カードの一部を変化させるなど
起動しているAnki
の上で動作するものをアドオン
と呼ぶらしい。
今回私が作るものは、
Anki
を起動せずとも外部からカードを追加するプラグイン
である。少し混乱させたら申し訳ない。
どうやら2.1.20
いろいろ刷新されている模様でドキュメントがわかりにくいところにあった。
以前はGitHub
からコードを取ってきてそれを読み込んでプラグインを書いていたようだがPyPI
なるものでパッケージをインストールさせようとしているので、コード本体をDLする必要がなくなったのだろうか?
Python
初心者のためよくわからないが、なんかNode.js
のpackage.json
っぽさを感じる。
めんどいので書いてある物を全部普通にインストールしてみる。
subprocess.check_call(["pip", "install", "mypy", "anki", "ankirspy", "aqt"])
コマンドプロンプトには上をそのまま変換して
pip install mypy anki ankirspy aqt
何の問題もなくインストール完了
とりあえずデータベースに直接カードを挿入していく場合は確かCollection
というAnki
のモジュール?から行う。(Python
ではモジュールと言っていいのだろうか?)
Anki
のライブラリそのものをpip
でインストールしたので以前とは違いスクリプトはどこに置いてもいいはず。適当にデスクトップにつくったフォルダにファイルを作ってみる。
test.py
from anki import Collection
col = Collection("C:/Users/{ユーザ名}/AppData/Roaming/Anki2/ユーザー 1/collection.anki2")
{ユーザ名}
となっている箇所は御存知の通りwindows
側のユーザ名で各自で違うので注意。
一方で最後のディレクトリの「ユーザ 1
」はAnki
側のデフォルトがこの名前なので複数のユーザーで同一のプログラムを使っていなければ概ね皆同じかと思う。変更している人もいるかもしれないので要注意。
またディレクトリはバックスラッシュではなくスラッシュである点/
に注意。
collection.anki2
というファイルを指定する。
python test.py
とりあえずエラーがでなければ成功
次の表示が出ている
reverting to stock json
よくわからないが解説にはcol.close()
を行わないとDBへの変更は破棄されると書いてあるので、そのまま変更せず戻したよということだろうか。
とりあえず成功のようだ。
昔のコードを見ると書き込みを確定する時にはcol.addNote
, col.save
を呼んでいるのでメソッドが変更されたのかもしれない。close
とsave
の違いは未検証。
Anki DB
の仕組み内部でSQLite
を使っている。テーブルが複雑で何をどう書き込んだらいいか分からなくなりそうだが、そのあたりはミスがないようにAnki
側にUIがある。
これを通して書き込めば良いのでユーザがSQL
を意識する必要はない点が素晴らしい設計。
database is locked
に注意プログラムを書いている最中にdatabase is locked
というエラーをよく見かける。
これは単純にAnki
本体が起動していてDB
を使用禁止にしているためだ。
必ずAnki
本体は終了して開発するように。テストでよく起動しっぱなしになっていることがある。
公式の説明は非常に簡素であるため古いメソッド名がそのまま使えるか試していく。
まずノートタイプを設定する。
これである。
カードを登録する場合はかならず必要。
表と裏だけの単純な暗記カードから、文章の空欄を埋める「穴埋め」タイプ、それ以外にもユーザーが独自にタイプを追加できるのがAnki
の特徴。
ちなみに英語リファレンスでもノート
のことをnote
と表記するがプログラム上はmodel
という単語を使うようなので混乱しないように。
先程のコードに次の行を追加してみよう。
anki_model_name = "すごいノート"
modelBasic = col.models.byName(anki_model_name) # ノートタイプの指定はこの2行
col.decks.current()['mid'] = modelBasic['id'] # ノートタイプの指定はこの2行
2行目は今はこうするものだとおぼえておく。
これで実行すると
TypeError: 'NoneType' object is not subscriptable
このエラーになるはずだ。上記の画像から分かるように「すごいノート
」というノートが存在しない。
では「すごいノート
」を「基本
」に変えて実行してみよう。
reverting to stock json
今度はエラーなし。
「基本
」というノートがAnki
側のDBに存在することが確認された => 新規作成するカードにノートタイプが関連付けできた、と言える。
まだ何も書き込んでないが内部的にこれで書き込むカードのノートタイプが設定されたはずだ。
まずここまででわかったことは古いバージョンと同じメソッドが使えるだろうということが実証できた。
中途半端だがとりあえずカード前処理のいち部がこれでテストできた。
次からは実際に新規カードが登録できるかやってみたい。
まとめると
GitHub
のAnki
をDLすることなくpip
で直接Anki
のライブラリを取ってくることによりプラグイン開発が出来るようになっているCollection
というモジュールを使う