0

私は基本的にdbから行ごとに構築し、ストリームをtcpソケットに送信し、別のスレッドがtcp応答をチェックしてエラー応答があるかどうかを判断し、特定のスチームをスキップして以前のスチームから再試行するPythonインターフェースを作成しています。

以下の擬似コード、PKはPrimaryKeyを意味します。

基本的にはこんな感じです

def generate_msg(pk_start, pk_stop):
    for x in db.query(pk>pk_startand pk<pk_stop):
        yield pack_to_stream(x)

その場合、tcpソケット送信スレッドは次のようになります。

for msg in generate_msg(first_id, last_id):
    socket.send(msg)

問題は、tcpソケットreadスレッドが応答でエラーを検出すると、msgのpkが返されるため、イテレータをから再起動する必要があることです。pk

だからここに私の質問があります:

  1. 特に、前後に移動できるイテレータの設計パートナーは何ですか。データベース行カーソルの操作
  2. リスト全体を読まなくても、そもそもイテレータの総数を取得できますか?
  3. 私のシナリオの一般的なアドバイスは何ですか?

ありがとう

4

1 に答える 1

1

イテレータは、一度に1つのアイテムを処理することでメモリを節約するように設計されており、無制限の数のアイテムを生成できる可能性があります。ただし、それらの設計の結果として、通常、イテレーター全体を消費せずにそれらの長さを知ることはできず、通常、それらを操作できるとは期待されていません。

とはいえ、イテレータとして使用でき、追加機能を提供できるカスタムクラスを作成することを妨げるものは何もありません。データベースカーソルは、そのようなクラスの標準的な例です。カーソルを繰り返して行を生成することもできますが、行数(シーケンスの長さ)を要求したり、列に関する追加情報を取得したり、複数の行を取得したり、.execute()メソッドを呼び出して新しい結果セットをポイントしたりすることもできます。 。

__iter__()イテレータとして機能するカスタムクラスを作成する場合は、メソッドを指定する必要があります。このメソッドを(yieldステートメントを使用して)ジェネレーターにするかreturn self、クラスに.next()メソッドを指定します。後者は1つのアイテムを返すか(使用しないでくださいyield)、またはそれ以上アイテムを返すことができなくなったときにレイズすることが期待されStopIterationます。

次に、長さ情報を返す他のメソッドを追加したり、特定の主キーから開始するようにクエリをリセットしたりできます。

テストされていない、Python風のコード:

class MessagesIterator(object):
    def __init__(self, pk_start, pk_stop):
        self.pk_start, self.pk_stop = pk_start, pk_stop
        self.cursor = db.query("pk>? and pk<?", (pk_start, pk_stop))

    def __iter__(self):
        return self

    def next(self):
        return next(self.cursor)  # raises StopIteration when done

    def length(self):
        return self.cursor.rowcount

    def move_to(self, pk_start):
        # Validate pk_start perhaps
        self.pk_start = pk_start
        self.cursor = db.query("pk>? and pk<?", (self.pk_start, self.pk_stop))
于 2012-11-23T09:05:53.727 に答える