2009-04-30 2 views
2

Прямо сейчас у меня есть mod_wsgi сценарий, который структурирован как это ..mod_wsgi выход выход буфера вместо возврата

def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/plain'), 
        ('Content-Length', str(len(output)))] 
    start_response(status, response_headers) 

    return [output] 

мне было интересно, если кто-нибудь знает способ, чтобы изменить это, чтобы работать на основе yield вместо return, таким образом я могу отправить страницу по мере ее создания и не только после ее завершения, поэтому загрузка страницы может ускориться для пользователя.

Однако, когда я поменять выход для списка и выход его в приложении(), он выдает ошибку:

TypeError: sequence of string values expected, value of type list found 
+0

, если вы в порядке с моим ответом, пожалуйста, выберите его как принятый. – nosklo

ответ

7
def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/plain'), 
        ('Content-Length', str(len(output)))] 
    start_response(status, response_headers) 

    yield output 

"However, whenever I swap the output for a list and yield it in the application(), it throws an error:"

Ну, не дают список. Выход каждого элемента вместо:

for part in mylist: 
    yield part 

или если список все содержимое, просто:

return mylist 

Поскольку список уже итератора и может дать сам по себе.

+1

Ха, да, я новичок. Теперь я вижу свою ошибку. :П – Ian

0

Не отправляйте длину контента и отправляйте результат по мере его получения. Вам не нужно знать размер вывода, если вы просто не делаете отправьте заголовок Content-Length. Таким образом, вы можете отправить часть ответа , прежде чем вы вычислите остальную часть.

def application(environ, start_response): 
    status = '200 OK' 
    output = 'Hello World!' 

    response_headers = [('Content-type', 'text/html')] 
    start_response(status, response_headers) 

    yield head() 
    yield part1() 
    yield part2() 
    yield part3() 
    yield "<!-- bye now! -->" 

В противном случае вы не получите никакой пользы от отправки на куски, поскольку вычисления выхода, вероятно, медленная часть и Интернет протокол будет посылать выходные данные в кусках в любом случае.

К сожалению, это не работает в том случае, когда, например, расчет из part2() решает, что вам действительно нужно, чтобы изменить заголовок (например, печенье) или необходимо создать другие страницы глобальных структур данных - если это когда-нибудь случится, вам нужно вычислить всю продукцию перед тем отправки заголовков, и, возможно, также используйте return [output]

Например http://aaron.oirt.rutgers.edu/myapp/docs/W1200_1200.config_template потребностей для создания страницы глобальной структуры данных для ссылок на подразделы , которые отображаются в верхней части страницы - так что последний подраздел должен быть отображен , прежде чем первый кусок выхода будет доставлен клиенту.

7

Обратите внимание, что «урожай» следует избегать, если это абсолютно необходимо. В частности, «урожайность» будет неэффективной, если уступить много мелких струн. Это связано с тем, что спецификация WSGI требует, чтобы после каждой строки было получено, что ответ должен быть сброшен. Для Apache/mod_wsgi промывка означает, что каждая строка вытесняется из выгружаемой ветровой системы и фильтрационной системы Apache и в сокет. Игнорируя накладные расходы системы фильтрации выходных файлов Apache, запись большого количества небольших строк в сокет просто просто плохо.

Эта проблема также существует, когда массив строк возвращается из приложения, поскольку флеш также должен выполняться между каждой строкой в ​​массиве. Это связано с тем, что строка обрабатывается как итерируемый, а не список.Таким образом, для предварительно сформированного списка строк гораздо лучше присоединить отдельные строки в одну большую строку и вернуть список, содержащий только одну строку. Выполнение этого также позволяет реализации WSGI автоматически генерировать Content-Length для ответа, если он явно не предоставлен.

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

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