Página inicial do Docs → Desenvolver aplicações → Drivers Python → PyMongo
Perguntas frequentes
Nesta página
- O PyMongo é seguro para threads?
- O PyMongo é seguro para fork?
- Posso usar o PyMongo com multiprocessamento?
- O PyMongo pode carregar os resultados de uma query como um Pandas DataFrame?
- Como funciona o pool de conexões no PyMongo?
- Por que o PyMongo adiciona um campo _id a todos os meus documentos?
- Como altero o valor de tempo limite dos cursores?
- Como posso armazenar
Decimal
instâncias? - Por que o PyMongo converte
9.99
em9.9900000000000002
? - O PyMongo suporta acesso no estilo de atributo para documentos?
- O PyMongo suporta frameworks assíncronas?
- O PyMongo funciona com mod_wsgi?
- O PyMongo funciona com PythonAnywhere?
- Como posso codificar meus documentos para JSON?
- O PyMongo se comporta de forma diferente no Python 3?
- Posso compartilhar ObjectIds em pedaços entre o Python 2 e o Python 3?
O PyMongo é seguro para threads?
Sim. O PyMongo é thread-safe e oferece pool de conexões integrado para aplicativos thread-safe.
O PyMongo é seguro para fork?
Não. Se você utilizar o método fork()
para criar um novo processo, não passe uma instância da classe MongoClient
do processo pai para o processo filho. Isto cria uma alta probabilidade de impasse entre as instâncias do MongoClient
no processo filho. Em vez disso, crie uma nova instância MongoClient
no processo filho.
Observação
O PyMongo tenta emitir um aviso se esse impasse puder ocorrer.
Posso usar o PyMongo com multiprocessamento?
Sim. No entanto, em sistemas Unix, o módulo de multiprocessamento gera processos usando o método fork()
. Isso acarreta os mesmos riscos descritos em O PyMongo é seguro para fork?
Para usar o multiprocessamento com o PyMongo, escreva código semelhante ao exemplo a seguir:
# 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()
Importante
Não copie uma instância da classe MongoClient
do processo pai para um processo filho.
O PyMongo pode carregar os resultados de uma query como um Pandas DataFrame?
Você pode usar a biblioteca PyMongoArrow para trabalhar com dados numéricos ou de colunas. PyMongoArrow permite carregar conjuntos de resultados de query do MongoDB como Pandas DataFrames, Arrays NumPy, ou Apache Arrow Tables.
Como funciona o pool de conexões no PyMongo?
Cada instância MongoClient
tem um pool de conexões integrado para cada servidor em sua topologia do MongoDB. Os pools de conexões abrem soquetes sob demanda para oferecer suporte a solicitações simultâneas ao MongoDB em seu aplicativo.
O tamanho máximo de cada conjunto de conexões é definido pela opção maxPoolSize
, que padroniza para 100
. Se o número de conexões em uso com um servidor atingir o valor de maxPoolSize
, a próxima solicitação para esse servidor aguardará até que uma conexão fique disponível.
Além dos soquetes necessários para dar suporte às solicitações do seu aplicativo, cada instância MongoClient
abre mais dois soquetes por servidor em sua topologia MongoDB para monitorar o estado do servidor. Por exemplo, um cliente conectado a um conjunto de réplicas de três nós abre seis soquetes de monitoramento. Se o aplicativo usar a configuração padrão para maxPoolSize
e executar queries apenas o nó primário (padrão), poderá haver no máximo 106
conexões totais na pool de conexões. Se o aplicativo usar uma preferência de leitura para executar queries nos nós secundários, esses pools de conexões crescerão e poderá haver 306
conexões totais.
Para dar suporte a um grande número de solicitações simultâneas do MongoDB em um processo, você pode aumentar maxPoolSize
.
Os pools de conexões têm taxa limitada. A opção maxConnecting
determina o número de conexões que o grupo pode criar em paralelo a qualquer momento. Por exemplo, se o valor de maxConnecting
for 2
, a terceira solicitação que tenta fazer check-out simultâneo de uma conexão será bem-sucedida somente quando ocorrer um dos seguintes casos:
O pool de conexões termina de criar uma conexão e há menos de
maxPoolSize
conexões no pool.Uma conexão existente é verificada novamente no pool.
A capacidade do driver de reutilizar conexões existentes melhora devido aos limites de taxa na criação de conexões.
Você pode configurar o número mínimo de conexões simultâneas para cada servidor com a opção minPoolSize
, que padroniza para 0
. O condutor inicia o pool de ligações com este número de tomadas. Se os soquetes forem fechados, fazendo com que o número total de soquetes (em uso e ociosos) caia abaixo do mínimo, mais soquetes serão abertos até que o mínimo seja atingido.
Você pode definir o número máximo de milésimos de segundo em que uma conexão pode permanecer ociosa no pool definindo a opção maxIdleTimeMS
. Depois que uma conexão fica inativa por maxIdleTimeMS
, o pool de conexões a remove e a substitui. O padrão desta opção é 0
(sem limite).
A seguinte configuração padrão para um MongoClient
funciona para a maioria dos aplicativos:
client = MongoClient(host, port)
MongoClient
suporta várias solicitações simultâneas. Para cada processo, crie um cliente e reutilize-o para todas as operações de um processo. Essa prática é mais eficiente do que criar um cliente para cada solicitação.
O driver não limita o número de solicitações que podem aguardar a disponibilidade de soquetes, e é responsabilidade do aplicativo limitar o tamanho de seu pool para limitar o enfileiramento durante um pico de carga. Os pedidos aguardam a quantidade de tempo especificada na opção waitQueueTimeoutMS
, que padroniza para 0
(sem limite).
Uma solicitação que aguarda mais do que o período de tempo definido por waitQueueTimeoutMS
para um soquete gera um erro ConnectionFailure
. Use essa opção se for mais importante limitar a duração das operações durante um pico de carga do que concluir cada operação.
Quando MongoClient.close()
é chamado por qualquer solicitação, o driver fecha todos os soquetes ociosos e fecha todos os soquetes que estão em uso à medida que são retornados ao pool. A chamada de MongoClient.close()
fecha somente os soquetes inativos, portanto, não é possível interromper ou encerrar nenhuma operação em andamento usando esse método. O condutor fecha estas tomadas apenas quando o processo é concluído.
Para obter mais informações, consulte a administração/connection-pool-overview/ na documentação do MongoDB Server .
Por que o PyMongo adiciona um campo _id a todos os meus documentos?
Quando você usa o método Collection.insert_one()
, o método Collection.insert_many()
ou o método Collection.bulk_write()
para inserir um documento no MongoDB e esse documento não inclui um campo _id
, o PyMongo adiciona automaticamente esse campo para você. Ele também define o valor do campo para uma instância de ObjectId
.
O exemplo de código a seguir insere um documento sem um campo _id
no MongoDB e, em seguida, imprime o documento. Depois de inserido, o documento contém um campo _id
cujo valor é uma instância de ObjectId
.
'x': 1} my_doc = { collection.insert_one(my_doc)InsertOneResult(ObjectId('560db337fba522189f171720'), acknowledged=True) my_doc{'x': 1, '_id': ObjectId('560db337fba522189f171720')}
O PyMongo adiciona um campo _id
desta maneira por alguns motivos:
Todos os documentos MongoDB devem ter um campo
_id
.Se o PyMongo inserir um documento sem um campo
_id
, o MongoDB adicionará um para si, mas não informará o valor de volta ao PyMongo para seu aplicativo usar.Copiar o documento antes de adicionar o campo
_id
é proibitivamente caro para a maioria dos aplicativos de alto volume de gravação.
Dica
Se você não quiser que o PyMongo adicione um _id
aos seus documentos, insira apenas os documentos aos quais seu aplicativo já adicionou um campo _id
.
Como altero o valor de tempo limite dos cursores?
O MongoDB não oferece suporte a tempos limite personalizados para cursores, mas você pode desativar os tempos limite do cursor. Para fazer isso, passe a opção no_cursor_timeout=True
para o método find()
.
Como posso armazenar Decimal
instâncias?
MongoDB v3.4 introduziu o tipo Decimal128
BSON, um valor de ponto flutuante baseado em decimal de 128bits capaz de emular arredondamento decimal com precisão exata. As versões 3.4 e posteriores do PyMongo também permitem este tipo. No entanto, as versões anteriores do MongoDB suportam apenas pontos flutuantes IEEE 754 , equivalentes ao tipo Python float
. O PyMongo pode armazenar instâncias Decimal
nessas versões do MongoDB somente convertendo-as para o tipo float
. Você deve realizar esta conversão explicitamente.
Para obter mais informações, consulte a documentação da API do PyMongo para decimal128.
Por que o PyMongo converte 9.99
em 9.9900000000000002
?
O MongoDB representa 9.99
como um valor de ponto flutuante IEEE, que não pode representar o valor com precisão. Isso também é verdade em algumas versões do Python. A esse respeito, o PyMongo se comporta da mesma forma que o shell JavaScript, todos os outros drivers do MongoDB e a própria linguagem Python.
O PyMongo suporta acesso no estilo de atributo para documentos?
Não. O PyMongo não implementa essa funcionalidade pelos seguintes motivos:
A adição de atributos polui o namespace do atributo para documentos e pode levar a bugs sutis ou erros confusos ao usar uma chave com o mesmo nome que um método de dicionário.
O PyMongo usa objetos SON em vez de dicionários regulares apenas para manter a ordem das chaves, porque o servidor exige isso para determinadas operações. Adicionar esse recurso complicaria a classe
SON
e poderia quebrar a compatibilidade com versões anteriores se o PyMongo voltasse a usar dicionários.Os documentos se comportam como dicionários, o que os torna relativamente simples de entender para novos usuários do PyMongo. Alterar o comportamento dos documentos adiciona uma restrição à entrada desses usuários.
Para obter mais informações, consulte o caso Jira relevante.
O PyMongo suporta frameworks assíncronas?
Sim. Para obter mais informações, consulte o guia Ferramentas de terceiros .
O PyMongo funciona com mod_wsgi?
Sim. Consulte mod_wsgi no guia Ferramentas.
O PyMongo funciona com PythonAnywhere?
Não. O PyMongo cria threads Python, que PythonAnywhere não suporta.
Para obter mais informações, consulte o ticket do Jira relevante.
Como posso codificar meus documentos para JSON?
O PyMongo suporta alguns tipos especiais, como ObjectId
e DBRef
, que não são suportados no JSON. Portanto, o módulo json
do Python não funcionará com todos os documentos no PyMongo. Em vez disso, o PyMongo inclui o json_util módulo, uma ferramenta para usar o json
módulo do Python com documentos BSON e o MongoDB Extended JSON.
python-bsonjs é outro conversor BSON-to-MongoDB-Extended-JSON, construído em cima do libbson. O python-bsonjs não depende do PyMongo e pode oferecer uma melhoria de desempenho em relação ao json_util
em determinados casos.
Dica
python-bsonjs funciona melhor com PyMongo ao usar o tipo RawBSONDocument
.
O PyMongo se comporta de forma diferente no Python 3?
O PyMongo codifica instâncias da classe bytes
como tipo BSON 5 (dados binários) com subtipo 0. Em Python 2, essas instâncias são decodificadas para Binary
com subtipo 0. Em Python 3, eles são decodificados de volta para bytes
.
Os seguintes exemplos de código usam o PyMongo para inserir uma instância do bytes
no MongoDB e então localizar a instância. No Python 2, a string de bytes é decodificada para Binary
. Em Python 3, a string de bytes é decodificada de volta para bytes
.
Da mesma forma, Python 2 e 3 se comportam de maneira diferente quando o PyMongo analisa valores binários JSON com subtipo 0. Em Python 2, esses valores são decodificados para instâncias de Binary
com subtipo 0. No Python 3, eles são decodificados em instâncias de bytes
.
Os seguintes exemplos de código utilizam o módulo json_util
para decodificar um valor binário JSON com subtipo 0. Em Python 2, a string de bytes é decodificada para Binary
. Em Python 3, a string de bytes é decodificada de volta para bytes
.
Posso compartilhar ObjectIds em pedaços entre o Python 2 e o Python 3?
Se você usar o Python 2 para extrair uma instância de ObjectId
, sempre poderá descartá-la com o Python 3. Para fazer isso, você deve passar a opção encoding='latin-1'
para o método pickle.loads()
. O exemplo de código a seguir mostra como extrair um ObjectId
no Python 2.7 e, em seguida, removê-lo no 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')
Se você selecionou um ObjectID
no Python 2 e deseja removê-lo no Python 3, deverá passar o argumento protocol
com um valor de 2
ou inferior para o método pickle.dumps()
. O exemplo de código a seguir mostra como extrair um ObjectId
no Python 3.7 e, em seguida, removê-lo no 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')