سؤال

دعونا نقول كنت ترغب في قراءة سطر من مأخذ ، باستخدام معيار 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()
هل كانت مفيدة؟

المحلول

على recv() دعوة التعامل معها مباشرة من خلال الاتصال على ج وظيفة المكتبة.

فإنه سيتم منع انتظار المقبس البيانات.في الواقع فإنه سيتم فقط السماح recv() نظام حظر المكالمات.

file.readline() فعالة مخزنة التنفيذ.ليس threadsafe ، لأنه يفترض انها واحدة فقط قراءة الملف.(على سبيل المثال عن طريق التخزين المؤقت القادمة الإدخال.)

إذا كنت تستخدم ملف كائن في كل مرة read() ويسمى إيجابي الحجة الأساسية الكود recv() فقط كمية البيانات المطلوبة إلا إذا كان بالفعل مخزنة.

فإنه سيكون مؤقتا إذا:

  • كنت قد دعا readline () ونصها الكامل العازلة

  • نهاية السطر قبل نهاية المخزن المؤقت

وبالتالي ترك البيانات في المخزن المؤقت.وإلا فإن العازلة عموما غير مملوء.

الهدف من السؤال ليس واضحا.إذا كنت بحاجة لمعرفة ما إذا كانت البيانات متاحة قبل القراءة ، يمكنك select() أو تعيين المقبس إلى nonblocking وضع مع s.setblocking(False).ثم يقرأ سيعود فارغة بدلا من حجب ، إذا كان هناك أي انتظار البيانات.

يمكنك قراءة ملف واحد أو مقبس متعددة المواضيع ؟ وأود أن وضع عامل واحد على قراءة مقبس التغذية البنود الواردة في طابور من أجل معالجة المواضيع الأخرى.

أقترح الاستشارات بيثون مأخذ وحدة المصدر و ج المصدر أن يجعل نظام المكالمات.

نصائح أخرى

إذا كنت قلقا مع الأداء والسيطرة على مأخذ تماما (كنت لا تمر قبل أن تتحول إلى مكتبة على سبيل المثال) ثم حاول تنفيذ التخزين المؤقت الخاصة بك في بيثون - بيثون 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,
  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 = []
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top