問題が発生しているかどうか、またはmongodbの利用可能なカーソル動作を理解できない場合は、誰かが私に理解を助けることができます。私はmongodb 2.0.4とpymongo 2.1.1を実行しています。pymongo tailableカーソルを空のコレクションで使用する
ここに問題を示すスクリプトがあります。
#!/usr/bin/python
import sys
import time
import pymongo
MONGO_SERVER = "127.0.0.1"
MONGO_DATABASE = "mdatabase"
MONGO_COLLECTION = "mcollection"
mongodb = pymongo.Connection(MONGO_SERVER, 27017)
database = mongodb[MONGO_DATABASE]
if MONGO_COLLECTION in database.collection_names():
database[MONGO_COLLECTION].drop()
print "creating capped collection"
database.create_collection(
MONGO_COLLECTION,
size=100000,
max=100,
capped=True
)
collection = database[MONGO_COLLECTION]
# Run this script with any parameter to add one record
# to the empty collection and see the code below
# loop correctly
#
if len(sys.argv[1:]):
collection.insert(
{
"key" : "value",
}
)
# Get a tailable cursor for our looping fun
cursor = collection.find({},
await_data=True,
tailable=True)
# This will catch ctrl-c and the error thrown if
# the collection is deleted while this script is
# running.
try:
# The cursor should remain alive, but if there
# is nothing in the collection, it dies after the
# first loop. Adding a single record will
# keep the cursor alive forever as I expected.
while cursor.alive:
print "Top of the loop"
try:
message = cursor.next()
print message
except StopIteration:
print "MongoDB, why you no block on read?!"
time.sleep(1)
except pymongo.errors.OperationFailure:
print "Delete the collection while running to see this."
except KeyboardInterrupt:
print "trl-C Ya!"
sys.exit(0)
print "and we're out"
# End
コードを見ると、私が持っている問題を実証するのはかなり簡単です。私は空のコレクション(適切にキャップされ、テールの準備ができている)に対してコードを実行すると、カーソルが死ぬと、私のコードは1つのループの後に終了します。コレクションに最初のレコードを追加すると、テーリングカーソルが動作するように動作するようになります。
また、StopIteration例外を処理すると、cursor.next()がデータを待機していますか?バックエンドがデータが利用可能になるまでブロックできないのはなぜですか?私はawait_dataが実際に何かをすると仮定していましたが、接続を待たずに接続を2〜2秒以上待つだけのようです。
ほとんどの例では、cursor.aliveループの周りに2番目のWhileループを入れていますが、スクリプトが空のコレクションの末尾に来ると、ループはスピンしてCPU時間を無駄にするだけです。私は実際にアプリケーションの起動時にこの問題を避けるために単一の偽のレコードを入れたくないのです。
何かを無限にブロックすることは決して良い考えではありません – mensi
gobject.MainLoop()。run();)に伝えてください – DaGoodBoy