トラブルシューティング
このページでは、MongoDB で PyMongo を使用する際に発生する一般的な問題の解決策を見つけることができます。
接続
サーバーはワイヤバージョン X を報告、PyMongo は Y が必要です
MongoDB Server v 3.6またはそれ以前のバージョンに接続しようとすると、PyMongo は次のエラーを発生させる可能性があります。
pymongo.errors.ConfigurationError: Server at localhost:27017 reports wire version 6, but this version of PyMongo requires at least 7 (MongoDB 4.0).
これは、接続先のサーバーに対してドライバーのバージョンが新しすぎる場合に発生します。 この問題を解決するには、次のいずれかを実行します。
MongoDBデプロイをv4.0 以降にアップグレードします。
MongoDB Server v3.6 以降をサポートするPyMongo 4.10 またはそれ以前のバージョンにダウングレードします。
PyMongo v3.x にダウングレードし、 MongoDB Server v2.6 以降をサポートします。
AutoReconnect
AutoReconnect
例外は、 フェイルオーバーが発生したことを示します。 これは、PyMongo がレプリカセットの元のプライマリ メンバーへの接続を失い、最後の操作が失敗した可能性があることを意味します。
このエラーが発生すると、PyMongo は自動的に後続の操作のために新しいプライマリ メンバーを検索しようとします。 エラーを処理するには、アプリケーションは次のいずれかのアクションを実行する必要があります。
失敗した可能性のある操作を再試行する
操作が失敗した可能性を認識しながら実行を続行
重要
PyMongo は、レプリカセットが新しいプライマリ メンバーを選出するまで、すべての操作でAutoReconnect
エラーを発生させます。
トンネルを使用して PyMongo から MongoDB にアクセスする際のタイムアウト
SSH トンネル経由で MongoDB レプリカセットに接続しようとすると、次のエラーが表示されます。
File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 1560, in count return self._count(cmd, collation, session) File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 1504, in _count with self._socket_for_reads() as (connection, slave_ok): File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__ return self.gen.next() File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 982, in _socket_for_reads server = topology.select_server(read_preference) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 224, in select_server address)) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 183, in select_servers selector, server_timeout, address) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 199, in _select_servers_loop self._error_message(selector)) pymongo.errors.ServerSelectionTimeoutError: localhost:27017: timed out
これは、PyMongo が他のレプリカセット ノードのアドレスとポートを含むisMaster
コマンドの応答を使用してレプリカセット ノードを検出するために発生します。 ただし、SSH トンネル経由でこれらのアドレスとポートにアクセスすることはできません。
代わりに、SSH トンネルでdirectConnection=True
オプションを使用することで、単一の MongoDB ノードに直接接続できます。
読み取り操作と書込み操作
AutoReconnect
エラー
読み込み設定(read preference)でtag-sets
を指定しており、MongoDB が指定されたタグを持つレプリカセット メンバーを見つけられない場合は、このエラーが表示されます。 このエラーを回避するには、タグセット リストの最後に空の辞書( {}
)を含めます。 これにより、一致するタグが見つからない場合は、読み取り参照モードに一致するノードから読み取るように PyMongo に指示します。
非推奨警告: カウントは非推奨
PyMongo はcount()
メソッドのサポートを終了しました。 代わりに、 Collection
クラスのcount_documents()
メソッドを使用します。
重要
count_documents()
メソッドはCollection
クラスに属します。 Cursor.count_documents()
を呼び出しようとすると、PyMongo は次のエラーを発生させます。
Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Cursor' object has no attribute 'count'
MongoClient が ConfigurationError に失敗
無効なキーワード引数名を指定すると、ドライバーはこのエラーを発生させます。
指定したキーワード引数が存在し、正しくスペルされていることを確認します。
Web アプリケーションで ObjectId を使用してドキュメントをクエリしても結果がない
次のコード例に示すように、ウェブ アプリケーションでは URL でドキュメントの ObjectId をエンコードするのが一般的です。
"/posts/50b3bda58a02fb9a84d8991e"
ウェブ フレームワークは、URL の ObjectId 部分を string としてリクエスト ハンドラーに渡します。 string をfind_one()
メソッドに渡す前に、 ObjectId
インスタンスに変換する必要があります。
次のコード例は、Flask アプリケーションでこの変換を実行する方法を示しています。プロセスは他のウェブ フレームワークでも同様です。
from pymongo import MongoClient from bson.objectid import ObjectId from flask import Flask, render_template client = MongoClient() app = Flask(__name__) def show_post(_id): # NOTE!: converting _id from string to ObjectId before passing to find_one post = client.db.posts.find_one({'_id': ObjectId(_id)}) return render_template('post.html', post=post) if __name__ == "__main__": app.run()
Cursors
「カーソル」オブジェクトには属性「_Cursor_killed」がありません
PyMongo v 3.8またはそれ以前のバージョンでは、 Cursor
コンストラクターに無効な引数を指定するとTypeError
とAttributeError
が発生します。 AttributeError
は関係ありませんが、 TypeError
には次の例に示すようにデバッグ情報が含まれています。
Exception ignored in: <function Cursor.__del__ at 0x1048129d8> ... AttributeError: 'Cursor' object has no attribute '_Cursor__killed' ... TypeError: __init__() got an unexpected keyword argument '<argument>'
これを修正するには、適切なキーワード引数を指定していることを確認してください。 また、PyMongo v 3.9以降にアップグレードすることで、関連性のないエラーも排除されます。
" CursorNotFound カーソル ID はサーバーで無効です "
MongoDB のカーソルは、サーバー上で操作が実行されずに長時間開いていると、サーバー上でタイムアウトすることがあります。 これにより、カーソルを反復処理しようとすると、 CursorNotFound
の例外が発生する可能性があります。
プロジェクション
<field>「インクルージョンプロジェクションのフィールド「フィールド」を除外できません」
単一のプロジェクションにフィールドを含め、除外しようとすると、ドライバーはこのメッセージとともにOperationFailure
を返します。 プロジェクションが、含めるフィールドまたは除外するフィールドのみを指定していることを確認します。
Indexes
DuplicateKeyException
一意なインデックスに違反する重複値を保存する書込み操作を実行すると、ドライバーはDuplicateKeyException
を発生させ、MongoDB は次のようなエラーを返します。
E11000 duplicate key error index
Data Formats
ValueError: UuidRepresentation.UNSpecIFIED を使用してネイティブ uuid.UUID をエンコードできません
このエラーは、次のコード例に示すように、UUID 表現がUNSPECIFIED
の場合に、ネイティブUUID
オブジェクトをBinary
オブジェクトにエンコードしようとした結果です。
unspecified_collection.insert_one({'_id': 'bar', 'uuid': uuid4()}) Traceback (most recent call last): ... ValueError: cannot encode native uuid.UUID with UuidRepresentation.UNSPECIFIED. UUIDs can be manually converted to bson.Binary instances using bson.Binary.from_uuid() or a different UuidRepresentation can be configured. See the documentation for UuidRepresentation for more information.
代わりに、次の例に示すように、 Binary.from_uuid()
メソッドを使用してネイティブ UUID をBinary
オブジェクトに明示的に変換する必要があります。
explicit_binary = Binary.from_uuid(uuid4(), UuidRepresentation.STANDARD) unspec_collection.insert_one({'_id': 'bar', 'uuid': explicit_binary})
別の言語のドライバーによって保存された日付をデコードするときにオーバーフローエラーが発生する
PyMongo は BSON datetime
値を Python のdatetime.datetime
クラスのインスタンスにデコードします。 datetime.datetime
のインスタンスは、 datetime.MINYEAR
( 1 )からdatetime.MAXYEAR
( 9999 )までの年に制限されています。 一部の MongoDB ドライバーは、 datetime.datetime
でサポートされている値より大幅に外側の年値を持つ BSON 日時を保存できます。
この問題を回避する方法がいくつかあります。 PyMongo 4.3以降、 bson.decode
は 4 つの方法のいずれかで BSON datetime
値を復号化できます。 変換方法は、 ~bson.codec_options.CodecOptions
のdatetime_conversion
パラメータを使用して指定できます。
デフォルトの変換オプションは~bson.codec_options.DatetimeConversion.DATETIME
です。これにより、値がdatetime.datetime
としてデコードされ、範囲外の日付に対して~builtin.OverflowError
が発生できるようになります。 ~bson.codec_options.DatetimeConversion.DATETIME_AUTO
はこの動作を変更して、表現が範囲外の場合には代わりに~bson.datetime_ms.DatetimeMS
を返し、以前のように~datetime.datetime
オブジェクトを返します。
from datetime import datetime from bson.datetime_ms import DatetimeMS from bson.codec_options import DatetimeConversion from pymongo import MongoClient client = MongoClient(datetime_conversion=DatetimeConversion.DATETIME_AUTO) client.db.collection.insert_one({"x": datetime(1970, 1, 1)}) client.db.collection.insert_one({"x": DatetimeMS(2**62)}) for x in client.db.collection.find(): print(x)
{'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)} {'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)}
その他のオプションについては、 DatetimeConversion の API ドキュメントを参照してください クラス。
datetime_conversion
の設定に関係のないもう 1 つのオプションは、 ~datetime.datetime
でサポートされている範囲外のドキュメント値をフィルタリングで除外することです。
from datetime import datetime coll = client.test.dates cur = coll.find({'dt': {'$gte': datetime.min, '$lte': datetime.max}})
datetime
の値が必要ない場合は、そのフィールドのみをフィルタリングで除外できます。
cur = coll.find({}, projection={'dt': False})
TLS
CERTTICATE_VERIFY_FAILED
次のようなエラー メッセージは、OpenSSL がサーバーの証明書を検証できなかったことを意味します。
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
これは、OpenSSL がシステムのルート証明書にアクセスできないか、証明書が古くなっているために多く発生します。
Linux を使用する場合は、Linux ベンダーから最新のルート証明書の更新がインストールされていることを確認してください。
macOS を使用しており、python.org からダウンロードした Python v 3.7以降を実行している場合は、 ルート証明書をインストールするには、次のコマンドを実行します。
open "/Applications/Python <YOUR PYTHON VERSION>/Install Certificates.command"
Tip
この問題の詳細については、 Python の問題29065 を参照してください。
port-pypy を使用する場合は、OpenSSL にルート証明書を見つける場所を指示するために環境変数を設定する必要がある場合があります。 次のコード例は、 認証モジュール をインストールする方法を示しています から Pypi に接続し、SSL_CERT_FILE
環境変数をエクスポートします。
$ pypy -m pip install certifi $ export SSL_CERT_FILE=$(pypy -c "import certifi; print(certifi.where())")
Tip
この問題の詳細については、 port-pypy の問題15 を参照してください。
TLSV 1 _ALERT_PROTOCOL_VERSION
次のようなエラーメッセージが表示された場合、Python で使用される OpenSSL バージョンでは、サーバーに接続するのに十分な新しい TLS プロトコルがサポートされていないことを意味します。
[SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version
業界のベストプラクティスでは、一部の MongoDB の配置で古い TLS プロトコルを無効にすることが推奨されています。また、一部の規則では、古い TLS プロトコルを無効にすることが推奨されています。 一部の配置では TLS 1.0が無効になり、他の配置では TLS 1.0および TLS 1.1が無効になる場合があります。
PyMongo が最新の TLS バージョンを使用するためにアプリケーションを変更する必要はありませんが、一部のオペレーティング システムのバージョンでは、それらをサポートするのに十分な新しい OpenSSL バージョンが提供されていない場合があります。
macOS v 10.12を使用している場合 (High Sierra)またはそれ以前の場合は、 python.org から Python をインストールします。 Homebrew、macports、または同様のソース。
Linux またはその他の macOS Unix を使用している場合は、次のコマンドを使用して OpenSSL バージョンを確認します。
openssl version
上記のコマンドで1.0.1未満のバージョン番号が表示されている場合、 TLS 1.1以降のサポートは利用できません。 新しいバージョンにアップグレードするか、OS ベンダーに解決策について問い合わせてください。
Python インタープリタの TLS バージョンを確認するには、 requests
モジュールをインストールして次のコードを実行します。
python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])"
TLS 1.1以降が表示されます。
無効なステータス応答
次のようなエラー メッセージが表示された場合、証明書失効チェックに失敗したことを意味します。
[('SSL routines', 'tls_process_initial_server_flight', 'invalid status response')]
詳細については、このガイドの「 OCSP 」セクションを参照してください。
SSLV 3 _ALERT_HANDSHAKE_FAILURE
Python v 3.10以降を v 4.0より前のバージョンの MongoDB で使用する場合、 次のメッセージのようなエラーが表示される場合があります。
SSL handshake failed: localhost:27017: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997) SSL handshake failed: localhost:27017: EOF occurred in violation of protocol (_ssl.c:997)
MongoDB Server ログには、次のエラーも表示される場合があります。
2021-06-30T21:22:44.917+0100 E NETWORK [conn16] SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher
Python v で ssl モジュールに加えられた変更3.10は v 4より前のバージョンの MongoDB と互換性がない可能性があります。 0 。 この問題を解決するには、次の手順の 1 つ以上を試してください。
Python を v 3.9またはそれ以前のバージョンにダウングレード
MongoDB Server を v 4.2以降にアップグレードする
OCSPオプションを使用して PyMongo をインストールする(PyOpenSSL に依存する)
レガシー再ネゴシエートが無効
OpenSSL v 3 以降を使用している場合、次のメッセージのようなエラーが表示される場合があります。
[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled
このようなエラーは、レガシーTLS 再ネゴシエートを誤って強制する、古くなった、またはバグのある SSL プロキシが原因で発生します。
この問題を解決するには、次の手順を実行します。
重要
UnsafeLegacyServerConnect
オプションを設定すると セキュリティ上の影響 があるため、 エラーに対処するための最後の手段としてこの回避策を使用してください。unsafe legacy renegotiation disabled
クライアント側操作タイムアウト
ServerSelectionTimeoutError
このエラーは、クライアントが指定されたタイムアウト内に操作を実行するために利用できるサーバーを見つけられなかったことを示しています。
pymongo.errors.ServerSelectionTimeoutError: No servers found yet, Timeout: -0.00202266700216569s, Topology Description: <TopologyDescription id: 63698e87cebfd22ab1bd2ae0, topology_type: Unknown, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None>]>
ネットワークタイムアウト
このエラーは、クライアントが指定されたタイムアウト内に接続を確立できなかったこと、または操作が送信されたがサーバーが時間内に応答しなかったことを示しています。
pymongo.errors.NetworkTimeout: localhost:27017: timed out
ExecutionTimeout
このエラーは、指定されたタイムアウトを超えたため、サーバーが操作をキャンセルしたことを示している可能性があります。 PyMongo がこの例外を発生させた場合でも、サーバー上で操作が部分的に完了している可能性があります。
pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'}
また、指定されたタイムアウト内に操作を完了できなかったため、クライアントが操作をキャンセルしたことを示す場合もあります。
pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427
WTimeoutError
このエラーは、サーバーが指定されたタイムアウト内に、指定された書込み保証 (write concern) に従って要求された書込み操作を完了できなかったことを示しています。
pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}
BulkWriteError
このエラーは、サーバーが指定されたタイムアウト内に、指定された書込み保証 (write concern) に従い、 メソッドまたは メソッドを完了できなかったことを示しています。insert_many()
bulk_write()
pymongo.errors.BulkWriteError: batch op errors occurred, full error: {'writeErrors': [], 'writeConcernErrors': [{'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []}
プロセスのフォーク
プロセスをフォークするとデッドロックが発生する
MongoClient
インスタンスは、接続されたサーバーの監視などのバックグラウンド タスクを実行するために複数のスレッドを生成します。 これらのスレッドは、 フォークセーフではない クラスのインスタンスによって保護されている状態を共有しますthreading.Lock
。PyMongo には、 threading.Lock
クラスまたはミューテックスを使用する他のマルチスレッド コードと同じ制限が適用されます。
これらの制限の 1 つは、 fork()
メソッドを呼び出した後にロックが使用できなくなることです。 fork()
が実行されると、ドライバーは親プロセスのすべてのロックを、親と同じ状態で子プロセスにコピーします。 親プロセスでロックされている場合は、子プロセスでもロックされます。 fork()
によって作成された子プロセスにはスレッドが 1 つしかないため、親プロセスの他のスレッドによって作成されたロックは、子プロセスでは解放されません。 子プロセスが次にこれらのロックのいずれかを取得しようとすると、デッドロックが発生します。
PyMongo バージョン4.3以降では、 os.fork()
メソッドを呼び出すと、ドライバーはos.register_at_fork()
メソッドを使用して子プロセス内のロックやその他の共有状態をリセットします。 これによりデッドロックの可能性は減りますが、PyMongo は OpenSSL などのマルチスレッド アプリケーションではフォークセーフでないライブラリに依存しています と getaddrinfo(3 ) 。そのため、デッドロックは引き続き発生する可能性があります。
fork の Linux マニュアルページ(2 ) また、次の制限も課されます。
fork()
マルチスレッド プログラムで の後、子は非同期シグナルセーフな関数のみを安全に呼び出せるようになります( シグナルセーフ(7 ) を参照してください )を、 execVE(2 )を呼び出すまで。
PyMongo は非同期シグナルセーフでない関数に依存しているため、子プロセスで実行するとデッドロックやクラッシュが発生する可能性があります。
Tip
子プロセスにおけるデッドロックの例については、 Python-3406 を参照してください。 Jira の。
を使用したマルチスレッド コンテキストでの ロックが発生する問題の詳細については、「 の問題Python 」を参照してください。fork()
を指定します。6721Python