Буферизация сокетов Python

Предположим, я хочу прочитать строку из сокета, используя стандартный модуль socket :

 def read_line(s): ret = '' while True: c = s.recv(1) if c == '\n' or c == '': break else: ret += c return ret 

Что именно происходит в s.recv(1) ? Будет ли он выдавать системный вызов каждый раз? В любом случае, я должен добавить некоторую буферизацию:

Для наилучшего соответствия аппаратным и сетевым реалиям значение bufsize должно быть относительно небольшой мощностью 2, например, 4096.

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

Но написать эффективную и потокобезопасную буферизацию не представляется возможным. Что делать, если я использую file.readline() ?

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

3 Solutions collect form web for “Буферизация сокетов Python”

Вызов recv() обрабатывается напрямую, вызывая функцию библиотеки C.

Он заблокирует ожидание того, что сокет будет иметь данные. На самом деле это просто позволит блокировать системный вызов recv() .

file.readline() – эффективная буферизованная реализация. Он не является потокобезопасным, потому что он предполагает, что он единственный, кто читает файл. (Например, путем буферизации предстоящего ввода.)

Если вы используете файл-объект, каждый раз, когда read() вызывается с положительным аргументом, базовый код будет recv() только объем запрашиваемых данных, если он уже не буферизирован.

Он будет буферизироваться, если:

  • вы вызвали readline (), который читает полный буфер

  • конец строки был до конца буфера

Таким образом, оставляя данные в буфере. В противном случае буфер обычно не переполняется.

Задача вопроса не ясна. если вам нужно увидеть, доступны ли данные перед чтением, вы можете select() или установить сокет в неблокирующий режим с помощью s.setblocking(False) . Затем чтение будет возвращать пустой, а не блокирующий, если нет ожидающих данных.

Вы читаете один файл или сокет с несколькими потоками? Я бы поставил одного работника на чтение сокета и подачу полученных предметов в очередь для обработки другими потоками.

Предложите консалтингу Python Socket Module source и C Source, который делает системные вызовы .

Если вы заинтересованы в производительности и полностью контролируете сокет (вы не передаете его в библиотеку, например), попробуйте реализовать собственную буферизацию в Python – Python string.find и string.split, и это может быть удивительно быстро.

 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 

Если вы ожидаете, что полезная нагрузка будет состоять из строк, которые не слишком велики, это должно выполняться довольно быстро и избежать излишнего перерасхода слишком много уровней вызовов функций. Мне было бы интересно узнать, как это сравнивается с file.readline () или с помощью 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, ie 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 = [] 
  • select.select () не улавливает исключительные условия на сокет?
  • Как получить порты, которые прослушивает процесс?
  • Сетевой чат Python
  • Python Socket Send Buffer Vs. улица
  • Отправить объект сокета для разветвленного процесса (multiprocessing.Queue)
  • socket.gaierror: Имя или услуга неизвестны
  • Который является большими накладными расходами: каждый раз создавайте новый сокет или поддерживая один сокет для передачи данных
  • как закрыть блокирующий сокет, пока он ждет приема данных?
  •  
    Interesting Posts for Van-Lav

    Повторное подключение к устройству с помощью pySerial

    Выполнение системных вызовов с веб-сервера

    Как запретить пользователям из моего приложения Django (с завихрением)

    Тензорный поток: как отображать пользовательские изображения в тензокартоне (например, графики Matplotlib)

    Проблемы Cython и deepcopy () с ссылочными методами / функциями. Любые альтернативные идеи?

    Зачем возвращать что-либо, кроме `self` из` __iadd__`?

    Закладка вкладки python в окнах

    cx_Freeze / ldap: ImportError: Ошибка загрузки DLL% 1 не является допустимым приложением Win32

    python: добавление словаря в список – я вижу указатель вроде поведения

    Является ли причина, по которой я не могу добавить ManyToManyField?

    Не удалось сохранить matplotlib.figure Рисунок, холст None

    Точечный продукт двух векторов в тензорном потоке

    Питонический способ перебора битов целого числа

    Как очистить эту веб-страницу с помощью Python и lxml? пустой список возвращен

    SVG на стороне сервера для PNG (или какой-либо другой формат изображения) в python

    Python - лучший язык программирования в мире.