Вопрос

Прямо сейчас у меня есть скрипт 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
Это было полезно?

Решение

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

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

Что ж, не отдавайте список.Вместо этого выдайте каждый элемент:

for part in mylist:
    yield part

или, если список представляет собой весь контент, просто:

return mylist

Потому что список уже является итератором и может выдавать результат сам по себе.

Другие советы

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

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

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

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

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() решает, что вам действительно нужно изменить заголовок (например, cookie) или необходимо создать другие глобальные структуры данных страницы -- если это когда-нибудь произойдет, вам нужно вычислить весь вывод перед отправкой заголовков, и с таким же успехом вы могли бы использовать return [output]

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top