Буферизация сокетов 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 = [] 
  • Подмена IP-адреса источника HTTP-запроса
  • NetDisturb с использованием Python
  • Python, Connectin отказано 10061
  • socket.gaierror: Имя или услуга неизвестны
  • Получите IP-маску от IP-адреса и длины маски в Python
  • Как (в какой форме) передать (доставить) функцию Python?
  • Python Sniffing из книги Black Hat Python
  • Python Sockets: включение режима Promiscuous в Linux
  •  
    Interesting Posts for Van-Lav

    Pyspark – ValueError: не удалось преобразовать строку в float / invalid literal для float ()

    не удалось установить настройки профиля Firefox с помощью Selenium (geckodriver 0.16)

    Почему Python не использует ^, чтобы обозначить квадрат числа, но вместо этого использует **?

    Построение временных рядов данных с использованием морского

    Подождите, пока не закончится определенный процесс (зная «pid»)

    передача нескольких переменных в os.system в python

    Как вы тестируете задачу Сельдерея?

    Протокол TCP и UDP

    Два витка трубы с процессом spawnProcess

    Предел верхней памяти?

    Почему этот фрагмент с shebang #! / Bin / sh и exec python внутри 4 одинарных кавычек работает?

    Моя легенда matplotlib.pyplot отключена

    Отображать данные, передаваемые из флага, при обновлении

    Как идентифицировать нефотографические или «неинтересные» изображения с использованием библиотеки изображений Python (PIL)

    Построение списка месяцев путем итерации между двумя датами в списке (Python)

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