Blow Up by Black Swan

アプリ制作時に悩まされたエラー集

前回の記事で新しく作ったアプリについて書きましたが、今回はそのアプリの制作過程で出会い、苦しめられたエラーをまとめました。ググってすぐ解決できたものは除外していますので、主にググっても大した情報が出てこなかった、ググったら情報は出てくるけど的を得たものがなく解決に時間がかかった、といったエラーです。ちなみに以前の記事の記事で紹介している、今回作ったアプリの利用動画は下記になります。

従業員向け利用動画

管理者向け利用動画

1. mysqlエラー: Commands out of sync; you can’t run this command now in your client code, you are calling client functions in the wrong order.

まずは、mysqlエラーからです。これはPythonスクリプトからMySQLに、複数のUPDATE文を実行指令したときに発生したエラーです。Pythonのデータベース関連のモジュールの共通仕様となっているDB APIに沿うとINSERTやUPDATE文の実行完了後、commitメソッドを実行する必要があります。これを実行しないと、データベースにSQL文の実行内容が反映されません。当初、複数のUPDATEを走らせる必要があり、私は次のように、複数のUPDATE文を走らせた後にcommitメソッドを実行するというようにコードを組んでいましたが、それが間違いでした。

UPDATE文
UPDATE文
UPDATE文
commit()

解決策

このエラーの解決方法はいたって簡単でした。それはそれぞれのUPDATE文ごとにcommitメソッドを実行するということです。先ほどのイメージ図を下のようにするだけでした。

UPDATE文
commit()
UPDATE文
commit()
UPDATE文
commit()

このようにコードを変えるだけで、エラーが解消されました。参考サイトは以下になります。より丁寧な説明が載っています。

2. mysqlエラー: Cannot add or update a child row: a foreign key constraint fails

これは外部キー制約のあるカラムにデータを入れようとしたときになんらかの原因で、外部キーで指定された値と一致せずに発生するエラーです。私の場合は、mysql.connectorモジュールでパラメータ付きのexecuteメソッドを実行するときに発生しました。

解決策

おそらくこのエラーはMySQLに渡された値のデータ型の違いでも発生するのではないかと思います。私の場合は、formatを使ってsql文に組み込んでいたのを、パラメータで指定する形にすることで解決しました。sql文で値が変わる部分はパラメータで渡すのが一般的だと思いますが、sql文の変形を行う上でformat文とパラメータをうまく使い分けた方が効果的だったためです。

cursor.execute(sql.format())

=> cursor.execute(sql, params)

3. mysql-connector-pythonエラー: mysql.connector.errors.InterfaceError: 2026 (HY000): SSL connection error: SSL_CTX_set_tmp_dh failed

次はmysql-connector-pythonについてのエラーです。レンタルサーバでプログラムを動かそうとしたときに発生したエラーです。最後のアプリのデプロイ時点で発生したので、とてもショックであり、意味がわからなすぎて解決するのに数日要しました。

解決策

結果的にこれはmysql-connector-pythonの内在する問題のようでした。バグみたいなものかもしれません。解決は諦め、mysqlのドライバーをPyMySQLに変えたら、うまく動きました。どうしても直す場合は、mysqlの設定を変更する必要があるようですが、レンタルサーバでは制限がかかって変更できなかったので、深追いするのをやめました。

4. pymysqlエラー: raise RuntimeError(“cryptography is required for sha256_password or caching_sha2_password”)

mysql-connector-pythonからpymysqlにmysqlドライバーを変えたときにいきなり起こったエラーです。またかよという感じで腹が立ちました。これは、ローカルでpymysqlを使おうとしたときに起こりました。mysqlサーバはdockerで立ち上げ、pycharmから実験的に動かそうとしたときです。

解決策

このエラーは、mysqlの認証のプラグインが原因でした。デフォルトの認証がcaching_sha2_passwordになっていたのですが、これだと暗号化がうまくいかないのか、復号の際の検証がうまくいかないのか、エラーが発生しているようです。そのため、この認証方式を一番シンプルなmysql_native_passwordに変えてしまえば、簡単にエラーが解消します。私は参考サイトの載っているように次のようにmysqlシェルでコマンドを走らせるだけでうまくいきました。

#①デフォルト認証式の確認
mysql> SELECT user, host, plugin FROM user;

#②対象ユーザーのデフォルト認証方式の変更
alter user 'user'@'host' identified WITH mysql_native_password by 'password';
Query OK, 0 rows affected

user,host,passwordには対応するデータを入れるだけです。ローカルでの実験用ですので、一番シンプルなものに変えてしまったのですが、本番環境等ではやはりsha2などのしっかりとしたハッシュ処理がされるものを使った方が良いと思います。参考サイトは以下になります。

5. jinja2エラー: jinja2.exceptions.TemplateAssertionError: no test named ‘None’

残りの2つはflask推奨のテンプレートパッケージ、jinja2に関するものです。まずは”None”に関するものです。テンプレートの中のif文で"変数" is Noneという形で条件式を作ったときに起こりました。

解決策

この解決策は==Nonenotを使う形に変更するだけで大丈夫です。jinja2ではisがPythonと異なる役割を果たしており、testsとして登録された関数を呼び出す機能があるようです。noneというテストがなければ、”noneと呼ばれるテストはない”というエラーが発生しまうとのことです。参考サイトは下記になります。

6. jinja2エラー: TemplateSyntaxError: expected token ‘:’, got ‘}’

最後のエラーです。このエラーは様々な場面で登場し、かなり私を苦しめたエラーの一つです。

解決策

このエラーの原因はいたってシンプルで、カッコで閉じ忘れている部分があるということです。たとえば、)]がなかったりといったことです。そのため、閉じ忘れているところがないかひたすら探す。これが解決策です。参考サイトは以下になります。

7. まとめ

今回はアプリ制作の過程で出会ったエラーについてまとめました。様々なエラーに出会いましたが、その中でも特に悩まされたものを中心にまとめています。以前、エラー対処にかかる時間と技術的難易度についての記事を読みましたが、エラーの技術的難易度と時間は必ずしも比例せず、むしろ時間がかかるものほど単なる見落としのようなイージーなエラーかもしれないと書いており、個人的にもまさにその通りだと感じています。

今回の記事で紹介しているエラーも実際は大したエラーではありませんが、かなり時間を要したものばかりです。エラーはものによって情報がかなり限られていることもあるので、少しでも日本語のエラー情報が増えればと思い、この記事を書きました。どなたかの参考になれば幸いです。