2009-06-02 2 views
0

В mod_wsgi я отправляю заголовки, запустив функцию start_response(), но все содержимое страницы передается с помощью yield/return. Есть ли способ передать содержимое страницы так же, как start_response()? Использование инструкции return.yield очень ограничительно, когда дело доходит до работы с фрагментированными данными.Передача данных в mod_wsgi

E.g.

def Application(): 

    b = buffer() 

    [... page code ...] 

    while True: 
     out = b.flush()  
     if out: 
      yield out 

class buffer: 

    def __init__(self):   
     b = [''] 
     l = 0 

    def add(self, s): 
     s = str(s) 
     l += len(s) 
     b.append(s) 

    def flush(self): 

     if self.l > 1000: 
      out = ''.join(b) 
      self.__init__() 
      return out 

Я хочу, чтобы иметь буфер вывода содержимого при загрузке страницы, но выводит только содержимое достаточно однажды она складывается (в этом, например, 1000 байт).

ответ

2

Нет; Но я не считаю это ограничительным. Возможно, вы хотите вставить пример кода, в котором вы описываете свое ограничение, и мы можем помочь.

Для работы с данными чанки вы просто yield ломтей:

def application(environ, start_response): 
    start_response('200 OK', [('Content-type', 'text/plain')] 
    yield 'Chunk 1\n'  
    yield 'Chunk 2\n'  
    yield 'Chunk 3\n' 
    for chunk in chunk_data_generator(): 
     yield chunk 

def chunk_data_generator() 
    yield 'Chunk 4\n' 
    yield 'Chunk 5\n' 

EDIT: Базирующийся в комментариях вы дали, пример нагромождения данных до определенной длины перед отправкой вперед:

BUFFER_SIZE = 10 # 10 bytes for testing. Use something bigger 
def application(environ, start_response): 
    start_response('200 OK', [('Content-type', 'text/plain')] 
    buffer = [] 
    size = 0 
    for chunk in chunk_generator(): 
     buffer.append(chunk) 
     size += len(chunk) 
     if size > BUFFER_SIZE: 
      for buf in buffer: 
       yield buf 
      buffer = [] 
      size = 0 

def chunk_data_generator() 
    yield 'Chunk 1\n'  
    yield 'Chunk 2\n'  
    yield 'Chunk 3\n' 
    yield 'Chunk 4\n' 
    yield 'Chunk 5\n' 
+0

Ну, это ограничение, потому что все уступки происходят в приложении() и не могут быть внедрены нигде. start_response() может быть размещен в любом месте приложения. Если бы я хотел запустить буфер вывода, который накапливает данные до определенной длины перед выходом в wsgi, это становится очень тяжелым, если не задействовать потоки. – Ian

+0

Я просто привел вам пример, где вы можете уступить где-то еще. Нет связанных нитей. Вы все еще неясно, в чем именно заключается ограничение. Поместите некоторый пример псевдо-кода на то, как вы хотите работать в своем вопросе, чтобы мы могли либо заставить его работать, либо сказать, почему это невозможно. – nosklo

+0

Я добавил пример, но проблема с моим примером заключается в том, что только буфер запускает результаты * после того, как * код страницы завершил выполнение, что в конце концов совпадает с тем, что я просто сделал обычный (не-chunked) ответ. – Ian

1

это возможно для приложения к «толчок» данные ЧТ e Сервер WSGI:

Некоторые существующие API-интерфейсы приложений поддерживают небуферизованный вывод иным образом, чем WSGI. В частности, они предоставляют функцию или способ записи, чтобы написать небуферизованный блок данных, или же они обеспечивают буферизованную функцию «write» и механизм «flush» для сброса буфера.

К сожалению, такие API не могут быть реализованы в терминах возвращаемого значения WSRI «итерируемого» приложения, если не используются нити или другие специальные механизмы.

Поэтому, чтобы позволить этим фреймворкам продолжать использовать императивный API, WSGI включает в себя специальный write() вызываемый, возвращенный start_response вызываемым.

Новые приложения и рамки WSGI не должны использовать write(), если это можно избежать.

http://www.python.org/dev/peps/pep-0333/#the-write-callable

Но это не рекомендуется.

Вообще говоря, приложения достигнут наилучшей пропускной способности путем буферизации их (скромного размера) вывода и отправки его сразу. Это общий подход в существующих структурах, таких как Zope: вывод буферизуется в StringIO или подобном объекте, а затем передается все одновременно, вместе с заголовками ответов.

Соответствующий подход в WSGI заключается в том, что приложение просто возвращает одноэлементный итеративный (например, список), содержащий тело ответа как одну строку. Это рекомендуемый подход для подавляющего большинства функций приложения, которые отображают HTML-страницы, текст которых легко вписывается в память.

http://www.python.org/dev/peps/pep-0333/#buffering-and-streaming

1

Если вы не хотите, чтобы изменить саму WSGI приложение частично буфер данных ответа перед отправкой, а затем реализовать WSGI промежуточного уровня, который оборачивает приложение WSGI и которая выполняет эту задачу.

Смежные вопросы