Frage

Lassen Sie uns sagen, ich will eine Linie von einem Socket lesen, die Standard-socket Modul:

def read_line(s):
    ret = ''

    while True:
        c = s.recv(1)

        if c == '\n' or c == '':
            break
        else:
            ret += c

    return ret

Was genau passiert in s.recv(1)? Wird es ein System, rufen jedes Mal ausstellen? Ich denke, ich soll eine gewissen Puffer hinzufügen, trotzdem:

  

Für beste Übereinstimmung mit Hardware und Netzwerk Realitäten, der Wert von bufsize sollte eine relativ geringe Potenz von 2 sein, beispielsweise 4096.

http://docs.python.org/library/socket. html # socket.socket.recv

Aber es scheint nicht einfach effizient und Thread-sichere Pufferung zu schreiben. Was passiert, wenn ich file.readline()?

# does this work well, is it efficiently buffered?
s.makefile().readline()
War es hilfreich?

Lösung

Der recv() Anruf behandelt wird direkt durch die C-Bibliothek-Funktion aufrufen.

Es wird gewartet Block für die Socket-Daten zu haben. In Wirklichkeit läßt es wird nur den recv() Systemaufruf Block.

file.readline() ist eine effiziente gepufferte Implementierung. Es ist nicht thread, weil sie es ist der einzige Lesen der Datei voraussetzt. (Zum Beispiel durch die kommenden Eingang Pufferung).

Wenn Sie die Datei-Objekt verwenden, jedes Mal read() mit einem positiven Argument aufgerufen wird, wird der zugrundeliegende Code recv() nur die Menge der Daten angefordert, es sei denn, es schon gepuffert wird.

Es wäre gepuffert werden, wenn:

  • Sie hatte genannt Readline- (), die einen vollständigen Puffer liest

  • das Ende der Leitung war vor dem Ende des Puffers

So Daten im Puffer zu verlassen. Andernfalls wird der Puffer im Allgemeinen nicht überfüllt.

Das Ziel der Frage ist nicht klar. wenn Sie sehen müssen, wenn Daten vor dem Lesen verfügbar sind, können Sie die Steckdose nicht blockierenden Modus mit select() s.setblocking(False) oder eingestellt. Dann liest leer zurückkehren, anstatt zu blockieren, wenn es keine Warte Daten vorhanden ist.

Lesen Sie eine Datei oder einen Sockel mit mehreren Threads? Ich würde die Buchse auf das Lesen eines einzelnen Arbeiter setzen und empfangenen Elemente in eine Warteschlange Einspeisen von anderen Threads für die Handhabung.

Python Socket-Beratung Modul Quelle und C Quelle das macht das System ruft .

Andere Tipps

Wenn Sie mit der Leistung besorgt und die Buchse vollständig kontrollieren (Sie übergeben es nicht in eine Bibliothek zum Beispiel) dann versuchen, die Umsetzung Ihre eigene Pufferung in Python - Python string.find und string.split und solche Dose sein erstaunlich schnell.

def linesplit(socket):
    buffer = socket.recv(4096)
    buffering = True
    while buffering:
        if "\n" in buffer:
            (line, buffer) = buffer.split("\n", 1)
            yield line + "\n"
        else:
            more = socket.recv(4096)
            if not more:
                buffering = False
            else:
                buffer += more
    if buffer:
        yield buffer

Wenn Sie erwarten, dass die Nutzlast von Linien bestehen das ist nicht zu groß, die ziemlich schnell laufen sollten, und vermeiden durch zu viele Schichten von Funktion Springen unnötig nennt. Ich wäre interessant zu wissen, Wie dies im Vergleich zu file.readline () oder unter Verwendung von socket.recv (1).

def buffered_readlines(pull_next_chunk, buf_size=4096):
  """
  pull_next_chunk is callable that should accept one positional argument max_len,
  i.e. socket.recv or file().read and returns string of up to max_len long or
  empty one when nothing left to read.

  >>> for line in buffered_readlines(socket.recv, 16384):
  ...   print line
    ...
  >>> # the following code won't read whole file into memory
  ... # before splitting it into lines like .readlines method
  ... # of file does. Also it won't block until FIFO-file is closed
  ...
  >>> for line in buffered_readlines(open('huge_file').read):
  ...   # process it on per-line basis
        ...
  >>>
  """
  chunks = []
  while True:
    chunk = pull_next_chunk(buf_size)
    if not chunk:
      if chunks:
        yield ''.join(chunks)
      break
    if not '\n' in chunk:
      chunks.append(chunk)
      continue
    chunk = chunk.split('\n')
    if chunks:
      yield ''.join(chunks + [chunk[0]])
    else:
      yield chunk[0]
    for line in chunk[1:-1]:
      yield line
    if chunk[-1]:
      chunks = [chunk[-1]]
    else:
      chunks = []
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top