자주 묻는 질문
이 페이지의 내용
- PyMongo는 스레드로부터 안전합니까?
- PyMongo는 포크에 안전하나요?
- PyMongo를 멀티프로세싱과 함께 사용할 수 있나요?
- PyMongo가 쿼리 결과를 Pandas DataFrame으로 로드할 수 있나요?
- PyMongo에서 연결 풀링은 어떻게 작동하나요?
- PyMongo가 모든 내 문서에 _id 필드를 추가하는 이유는 무엇인가요?
- 커서의 시간 초과 값을 변경하려면 어떻게 해야 하나요?
Decimal
인스턴스를 저장하려면 어떻게 해야 하나요?- PyMongo가
9.99
을9.9900000000000002
로 변환하는 이유는 무엇인가요? - PyMongo는 문서에 대한 속성 스타일 액세스를 지원하나요?
- PyMongo는 비동기 프레임워크를 지원하나요?
- PyMongo는 mod_wsgi와 함께 작동하나요?
- PyMongo는 PythonAnywhere와 함께 작동하나요?
- 내 문서를 JSON으로 인코딩하려면 어떻게 해야 하나요?
- PyMongo는 Python 3 에서 다르게 동작하나요?
- Python 2 와 Python 3 간에 절인 ObjectId를 공유할 수 있나요?
PyMongo는 스레드로부터 안전합니까?
네. PyMongo는 스레드로부터 안전하며 스레드 애플리케이션을 위한 내장 연결 풀링을 제공합니다.
PyMongo는 포크에 안전하나요?
아니요. fork()
메서드를 사용하여 새 프로세스를 만드는 경우 상위 프로세스의 MongoClient
클래스 인스턴스를 하위 프로세스로 전달하지 마세요. 이로 인해 하위 프로세스의 MongoClient
인스턴스 간에 교착 상태가 발생할 가능성이 높습니다. 대신 하위 프로세스에 새 MongoClient
인스턴스를 만듭니다.
참고
PyMongo는 이 교착 상태가 발생할 수 있는 경우 경고를 발행하려고 시도합니다.
PyMongo를 멀티프로세싱과 함께 사용할 수 있나요?
네. 그러나 Unix 시스템에서는 멀티프로세싱 모듈이 fork()
메서드를 사용하여 프로세스를 생성합니다. 이는 PyMongo 포크에 안전한가요?에 설명된 것과 동일한 위험을 수반합니다.
PyMongo에서 멀티프로세싱을 사용하려면 다음 예제와 유사한 코드를 작성하세요.
# Each process creates its own instance of MongoClient. def func(): db = pymongo.MongoClient().mydb # Do something with db. proc = multiprocessing.Process(target=func) proc.start()
중요
MongoClient
클래스의 인스턴스를 상위 프로세스에서 하위 프로세스로 복사하지 마세요.
PyMongo가 쿼리 결과를 Pandas DataFrame으로 로드할 수 있나요?
PyMongoArrow 라이브러리를 사용하여 숫자 또는 열 형식 데이터로 작업할 수 있습니다. PyMongoArrow를 사용하면 MongoDB 쿼리 결과 세트를 Pandas DataFrames, NumPy ndarrays 또는 Apache Arrow Tables로 로드할 수 있습니다.
PyMongo에서 연결 풀링은 어떻게 작동하나요?
모든 MongoClient
인스턴스에는 MongoDB 토폴로지의 각 서버에 대한 기본 연결 풀이 제공됩니다. 연결 풀은 요청 시 소켓을 열어 애플리케이션에서 MongoDB에 대한 동시 요청을 지원합니다.
각 연결 풀의 최대 크기는 maxPoolSize
옵션으로 설정되며 기본값은 100
입니다. 서버에 대한 사용 중인 연결 수가 maxPoolSize
값에 도달하면 해당 서버에 대한 다음 요청은 연결이 가능해질 때까지 대기합니다.
애플리케이션의 요청을 지원하는 데 필요한 소켓 외에도 각 MongoClient
인스턴스는 MongoDB 토폴로지에서 서버당 두 개의 추가 소켓을 열어 서버 상태를 모니터링합니다. 예를 들어, 3노드 복제본 세트에 연결된 클라이언트는 6개의 모니터링 소켓을 엽니다. 애플리케이션이 maxPoolSize
기본 설정을 사용하고 프라이머리 노드만 쿼리하는 경우 연결 풀에는 최대 총 106
개의 연결이 있을 수 있습니다. 애플리케이션이 읽기 설정을 사용하여 세컨더리 노드를 쿼리하는 경우, 연결 풀이 커져 총 연결 수가 306
개가 될 수 있습니다.
하나의 프로세스 내에서 많은 수의 동시 MongoDB 요청을 지원하려면 maxPoolSize
를 늘리면 됩니다.
연결 풀은 속도 제한이 있습니다. maxConnecting
옵션은 풀이 언제든지 병렬로 생성할 수 있는 연결 수를 결정합니다. 예를 들어 maxConnecting
의 값이 2
인 경우, 연결을 동시에 체크아웃하려는 세 번째 요청은 다음 경우 중 하나가 발생할 때만 성공합니다.
연결 풀에서 연결 생성이 완료되었으며 풀에 연결 수가
maxPoolSize
미만입니다.기존 연결이 풀로 다시 확인됩니다.
연결 생성에 대한 속도 제한으로 인해 기존 연결을 재사용하는 드라이버의 기능이 향상됩니다.
minPoolSize
옵션(기본값 0
)을 사용하여 각 서버에 대한 최소 동시 연결 수를 설정할 수 있습니다. 드라이버는 이 수의 소켓으로 연결 풀을 초기화합니다. 소켓이 닫혀 총 소켓 수(사용 중인 소켓과 유휴 상태 모두)가 최소값 아래로 떨어지면 최소값에 도달할 때까지 더 많은 소켓이 열립니다.
maxIdleTimeMS
옵션을 설정하여 연결이 풀에서 유휴 상태로 유지될 수 있는 최대 시간(밀리초)을 설정할 수 있습니다. 연결이 maxIdleTimeMS
동안 유휴 상태이면 연결 풀이 이를 제거하고 교체합니다. 이 옵션의 기본값은 0
(제한 없음)입니다.
MongoClient
에 대한 다음 기본 구성은 대부분의 애플리케이션에서 작동합니다.
client = MongoClient(host, port)
MongoClient
여러 개의 동시 요청을 지원합니다. 각 프로세스에 대해 클라이언트를 만들어 프로세스의 모든 작업에 재사용합니다. 이 방법은 각 요청에 대해 클라이언트를 만드는 것보다 더 효율적입니다.
드라이버는 소켓이 사용 가능해질 때까지 기다릴 수 있는 요청 수를 제한하지 않으며, 부하 급증 시 해당 풀의 크기를 대기 중인 제한으로 제한하는 것은 애플리케이션의 책임입니다. 요청은 waitQueueTimeoutMS
옵션에 지정된 시간 동안 대기하며 기본값은 0
(제한 없음)입니다.
소켓에 대해 waitQueueTimeoutMS
에 정의된 시간보다 오래 기다리는 요청은 ConnectionFailure
오류를 발생시킵니다. 모든 작업을 완료하는 것보다 부하가 급증하는 동안 작업 기간을 제한하는 것이 더 중요한 경우 이 옵션을 사용합니다.
요청에 의해 MongoClient.close()
가 호출되면 드라이버는 모든 유휴 소켓을 닫고 풀로 반환될 때 사용 중인 소켓을 모두 닫습니다. MongoClient.close()
를 호출하면 비활성 소켓만 닫히므로 이 메서드를 사용하여 진행 중인 작업을 중단하거나 종료할 수 없습니다. 드라이버는 프로세스가 완료될 때만 이러한 소켓을 닫습니다.
자세한 내용은 MongoDB Server 설명서의 연결 풀 개요 를 참조하세요.
PyMongo가 모든 내 문서에 _id 필드를 추가하는 이유는 무엇인가요?
Collection.insert_one()
메서드, Collection.insert_many()
메서드 또는 Collection.bulk_write()
메서드를 사용하여 MongoDB에 문서를 삽입할 때 해당 문서에 _id
필드가 포함되어 있지 않은 경우 PyMongo가 이 필드를 자동으로 추가합니다. 또한 필드 값을 ObjectId
인스턴스로 설정합니다.
다음 코드 예시에서는 _id
필드가 없는 문서를 MongoDB에 삽입한 다음 문서를 인쇄합니다. 삽입된 후 문서에는 값이 ObjectId
인스턴스인 _id
필드가 포함됩니다.
'x': 1} my_doc = { collection.insert_one(my_doc)InsertOneResult(ObjectId('560db337fba522189f171720'), acknowledged=True) my_doc{'x': 1, '_id': ObjectId('560db337fba522189f171720')}
PyMongo는 다음과 같은 몇 가지 이유로 이러한 방식으로 _id
필드를 추가합니다.
모든 MongoDB 문서에는
_id
필드가 있어야 합니다.PyMongo가
_id
필드 없이 문서를 삽입하는 경우, MongoDB는 자체적으로 문서를 추가하지만 애플리케이션에서 사용할 수 있도록 값을 PyMongo에 다시 보고하지는 않습니다._id
필드를 추가하기 전에 문서를 복사하는 것은 쓰기 볼륨이 큰 대부분의 애플리케이션에서 비용이 많이 듭니다.
팁
PyMongo가 문서에 _id
를 추가하지 않도록 하려면 애플리케이션에서 이미 _id
필드를 추가한 문서만 삽입하세요.
커서의 시간 초과 값을 변경하려면 어떻게 해야 하나요?
MongoDB는 커서에 대한 사용자 지정 시간 초과를 지원하지 않지만 커서 시간 초과를 끌 수 있습니다. 이렇게 하려면 no_cursor_timeout=True
옵션을 find()
메서드에 전달합니다.
인스턴스를 저장하려면 어떻게 Decimal
해야 하나요?
MongoDB v3.4 은(는) 정확한 정밀도로 소수점 반올림을 에뮬레이션할 수 있는 128비트 십진수 기반 부동 소수점 값인 Decimal128
BSON type을 도입했습니다. PyMongo 버전 3.4 이상에서도 이 유형을 지원합니다. 그러나 이전 MongoDB 버전에서는 Python float
유형에 해당하는 IEEE 754 부동 소수점만 지원합니다. PyMongo는 Decimal
인스턴스를 이러한 버전의 MongoDB에 float
유형으로 변환해야만 저장할 수 있습니다. 이 변환은 명시적으로 수행해야 합니다.
PyMongo 가 을 로 변환하는 이유는 9.99
9.9900000000000002
무엇인가요?
MongoDB는 9.99
을 IEEE 부동 소수점 값으로 나타내므로 값을 정확하게 표현할 수 없습니다. 이는 일부 Python 버전에서도 마찬가지입니다. 이와 관련하여 PyMongo 는 JavaScript shell, 다른 모든 MongoDB 드라이버 및 Python 언어 자체와 동일한 방식으로 작동합니다.
PyMongo는 문서에 대한 속성 스타일 액세스를 지원하나요?
아니요. PyMongo는 다음과 같은 이유로 이 기능을 구현하지 않습니다.
속성을 추가하면 문서의 속성 네임스페이스가 오염되고 딕셔너리 메서드와 동일한 이름의 키를 사용할 때 미묘한 버그나 혼란스러운 오류가 발생할 수 있습니다.
PyMongo는 서버가 특정 작업에 SON 객체를 요구하기 때문에 키 순서를 유지하기 위해서만 일반 사전 대신 SON 객체를 사용합니다. 이 기능을 추가하면
SON
클래스가 복잡해지고 PyMongo가 사전 사용으로 되돌아가면 이전 버전과의 호환성이 손상될 수 있습니다.문서는 딕셔너리처럼 작동하므로 새로운 PyMongo 사용자가 비교적 쉽게 이해할 수 있습니다. 문서의 동작을 변경하면 이러한 사용자의 진입 장벽이 추가됩니다.
자세한 내용은 관련 Jira 사례를 참조하세요.
PyMongo는 비동기 프레임워크를 지원하나요?
네. 자세한 내용은 타사 도구 가이드 를 참조하세요.
PyMongo는 mod_wsgi와 함께 작동하나요?
네. 도구 가이드 에서 mod_wsgi 를 참조하세요.
PyMongo는 PythonAnywhere와 함께 작동하나요?
아니요. PyMongo 는 Python 스레드를 생성합니다. 지원하지 않습니다.
자세한 내용은 관련 Jira 티켓을 참조하세요.
내 문서를 JSON으로 인코딩하려면 어떻게 해야 하나요?
PyMongo는 JSON에서 지원되지 않는 ObjectId
및 DBRef
과 같은 몇 가지 특수 유형을 지원합니다. 따라서 Python의 json
모듈은 PyMongo의 모든 문서에서 작동하지 않습니다. 대신 PyMongo에는 json_util 이 포함됩니다. 모듈은 json
BSON 문서 및 MongoDB 확장 JSON 과 함께 Python의 모듈을 사용하기 위한 도구입니다.
python-bsonjs 은(는)libbson 위에 구축된 또 다른 BSON-to-MongoDB-Extended-JSON 변환기입니다. . python-bsonjs는 PyMongo에 의존하지 않으며, 경우에 따라 json_util
보다 성능 향상을 제공할 수 있습니다.
팁
python-bsonjs는 RawBSONDocument
유형을 사용할 때 PyMongo와 가장 잘 작동합니다.
PyMongo는 Python 3 에서 다르게 동작하나요?
PyMongo는 bytes
클래스의 인스턴스를 하위 유형 0 가 있는 BSON 유형 5 (바이너리 데이터)로 인코딩합니다. Python 2 에서 이러한 인스턴스는 하위 유형이 0 인 Binary
로 디코딩됩니다. Python 3 에서는 bytes
로 다시 디코딩됩니다.
다음 코드 예제에서는 PyMongo를 사용하여 bytes
인스턴스를 MongoDB에 삽입한 다음 인스턴스를 찾습니다. Python 2에서 바이트 string 은 Binary
로 디코딩됩니다. Python 3에서 바이트 string 은 bytes
로 다시 디코딩됩니다.
import pymongo c = pymongo.MongoClient()'binary': b'this is a byte string'}).inserted_id c.test.bintest.insert_one({ObjectId('4f9086b1fba5222021000000') c.test.bintest.find_one(){u'binary': Binary('this is a byte string', 0), u'_id': ObjectId('4f9086b1fba5222021000000')}
import pymongo c = pymongo.MongoClient()'binary': b'this is a byte string'}).inserted_id c.test.bintest.insert_one({ObjectId('4f9086b1fba5222021000000') c.test.bintest.find_one(){'binary': b'this is a byte string', '_id': ObjectId('4f9086b1fba5222021000000')}
마찬가지로, Python 2 및 3 은 PyMongo가 하위 유형 0 로 JSON 바이너리 값을 구문 분석할 때 다르게 작동합니다. Python 2 에서 이러한 값은 하위 유형 0 의 Binary
인스턴스로 디코딩됩니다. Python 3 에서는 bytes
인스턴스로 디코딩됩니다.
다음 코드 예제에서는 json_util
모듈을 사용하여 하위 유형이 0 인 JSON 바이너리 값을 디코딩합니다. Python 2에서 바이트 string 은 Binary
로 디코딩됩니다. Python 3에서 바이트 string 은 bytes
로 다시 디코딩됩니다.
from bson.json_util import loads '{"b": {"$binary": "dGhpcyBpcyBhIGJ5dGUgc3RyaW5n", "$type": "00"}}') loads({u'b': Binary('this is a byte string', 0)}
from bson.json_util import loads '{"b": {"$binary": "dGhpcyBpcyBhIGJ5dGUgc3RyaW5n", "$type": "00"}}') loads({'b': b'this is a byte string'}
Python 2 와 Python 3 간에 절인 ObjectId를 공유할 수 있나요?
Python 2 을(를) 사용하여 ObjectId
인스턴스를 피클링하는 경우, 언제든지 Python 3 으)로 피클링을 해제할 수 있습니다. 이렇게 하려면 encoding='latin-1'
옵션을 pickle.loads()
메서드에 전달해야 합니다. 다음 코드 예시는 Python 2.7 에서 ObjectId
를 피클링한 다음 Python 3.7 에서 피클링을 해제하는 방법을 보여줍니다.
# Python 2.7 import pickle from bson.objectid import ObjectId oid = ObjectId() oidObjectId('4f919ba2fba5225b84000000') pickle.dumps(oid)'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...' # Python 3.7 import pickle b'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...', encoding='latin-1') pickle.loads(ObjectId('4f919ba2fba5225b84000000')
Python 2 에서 ObjectID
를 피클링하고 Python 3 에서 피클링을 해제하려면 pickle.dumps()
메서드에 값이 2
이하인 protocol
인수를 전달해야 합니다. 다음 코드 예시는 Python 3.7 에서 ObjectId
를 피클링한 다음 Python 2 에서 피클링을 해제하는 방법을 보여줍니다.7:
# Python 3.7 import pickle from bson.objectid import ObjectId oid = ObjectId() oidObjectId('4f96f20c430ee6bd06000000') 2) pickle.dumps(oid, protocol=b'\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...' # Python 2.7 import pickle '\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...') pickle.loads(ObjectId('4f96f20c430ee6bd06000000')