Смешивание и подгонка web-компонентов при помощи интерфейса Python WSGI

Изучаем стандарт языка Python для создания web-приложений с максимальной гибкостью

В статье приведены основные сведения по интерфейсу WSGI (Web Server Gateway Interface, Шлюзовый интерфейс web-сервера), а также показано, как создавать компоненты, которые можно включить в хорошо спроектированные web-приложения.

Уче Огбуйи (Uche Ogbuji), главный консультант, корпорации Fourthought

Photo: Уче ОгбуйиУче Огбуйи (Uche Ogbuji) является консультантом и соучредителем корпорации Fourthought, которая занимается поставкой и консультационными услугами в области XML-решений для корпоративного управления знаниями. Корпорация Fourthought разрабатывает 4Suite, платформу с открытым исходным кодом для XML, RDF и приложений управления знаниями. Огбуйи также является ведущим разработчиком Versa - языка запросов RDF. Специалист по компьютерной технике и писатель, Огбуйи родился в Нигерии, в данной время проживает и работает в г. Боулдер, Колорадо, США. Связаться с ним можно по электронной почте uche@ogbuji.net.



29.01.2007

Основа успеха в интернете - это гибкость. В нем Вы обнаружите столько способов проектирования, разработки и размещения web-сайтов и приложений, сколько существует разработчиков. Имея такой большой запас средств, web-разработчик часто выбирает уникальную комбинацию инструментов web-проектирования, стилей страниц, языка контента, типа web-сервера, промежуточного программного обеспечения и технологии DBMS, используя при этом различные языки реализации и дополнительные наборы инструментов. Чтобы добиться работы всех этих элементов с максимальной гибкостью, web-функции должны предоставляться по мере возможности в виде компонентов. Эти компоненты должны компетентно выполнять ограниченное число конкретных задач и хорошо стыковаться друг с другом. Легко сказать, но очень трудно осуществить на практике из-за большого количества различных подходов к web-технологиям.

Остается надеяться только на появление стандартов обеспечения функциональной совместимости web-компонентов. Некоторые из этих важных стандартов уже разработаны и составляют сущность наиболее успешных платформ для web-разработки. Среди наиболее заметных примеров - API сервлетов Java и инфраструктура Ruby on Rails. Некоторые языки программирования, давно распространенные в среде web-разработки, только в последнее время получили тот же уровень компонентной структуры и были изучены на опыте предыдущих стандартов компонентов платформ для web-разработки. Один из примеров - это Zend Framework для языка PHP (см. раздел Ресурсы). Еще один пример - это шлюзовый интерфейс web-сервера, Web Server Gateway Interface (WSGI) для Python.

Многие выражали недовольство тем, что популярный язык программирования Python имеет слишком много инфраструктур для web-разработки, от хорошо известных новых разработок, таких как Zope, до не слишком заметных, например, SkunkWeb. Некоторые соглашаются с тем, что такое разнообразие могло бы стать неплохим вариантом, если бы добавить к нему стандартизацию. Эксперт по Python и интернету Филип Дж. Эби (Phillip J. Eby) исходит из задачи такой стандартизации. Он разработал стандарт Python Enhancement Proposal (PEP) 333, в котором дано определение интерфейса WSGI.

Задача интерфейса WSGI - предоставить возможности для большей функциональной совместимости между инфраструктурами Python. Успех WSGI привел к появлению экосистемы подключаемых компонентов, которые можно использовать с любой излюбленной инфраструктурой для большей гибкости. В этой статье я расскажу о WSGI, главным образом, о его использовании в качестве архитектуры web-компонентов многократного использования. В описании и примерах программ предполагается, что вы используете Python 2.4 или более позднюю версию.

Базовая архитектура WSGI

WSGI разрабатывался с достаточно строгими ограничениями, но наиболее важным из них была необходимость достаточной обратной совместимости с предшествовавшими этому стандарту инфраструктурами интернета. Это ограничение означает, что, к сожалению, WSGI не так лаконичен и прозрачен, как Python, используемый разработчиками. Обычно непосредственно с WSGI имеют дело только те разработчики, которе создают инфраструктуры и компоненты многократного использования. Большинство обычных web-разработчиков выбирают инфраструктуру на основе ее легкости в применении; поэтому они изолированы от деталей WSGI.

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

Рисунок 1. Иллюстрация прохода запроса-ответа HTTP через стек WSGI
Стек WSGI

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

Промежуточные программы

Промежуточное программное обеспечение - это самый естественный уровень компонентов многократного использования. Промежуточные программы WSGI похожи и на приложения нижних уровней, и на сервер высшего уровня. Они следят за состоянием запросов, ответов и окружением WSGI, чтобы добавить некоторые особые функции. К сожалению, спецификация WSGI предлагает очень скудные примеры промежуточного программного обеспечения, а многие другие примеры, которые можно найти, слишком просты, чтобы можно было понять, как быстро написать свою промежуточную программу. Я расскажу о процессе работы промежуточного программного обеспечения WSGI и сделаю вывод о его перспективах. Я не буду затрагивать вопросы, которые не беспокоят большинство авторов промежуточных программ. Применительно к Python: если используется слово функция, то имеется в виду любой вызываемый объект.

  • Фаза загрузки. Фаза загрузки имеет место при каждом запуске web-сервера. Она принимает экземпляр промежуточной программы, которая инкапсулирует прикладную функцию;
  • Обработка запроса клиента. Обработка запроса клиента происходит при каждом получении запроса web-сервером:
    1. Сервер вызывает функцию промежуточного программного обеспечения с конфигурацией и параметрами server.start_response;
    2. Промежуточное программное обеспечение обрабатывает конфигурацию и вызывает прикладную функцию, соответствующую конфигурации и инкапсулированной функции middleware.start_response;
    3. Выполняется приложение; сначала оно подготавливает заголовок ответа, а затем вызывает функцию middleware.start_response;
    4. Промежуточное программное обеспечение обрабатывает заголовки ответа и вызывает функцию server.start_response;
    5. Сервер передает управление обратно промежуточной программе, а затем приложению, которое начинает возвращать блоки тела ответа (в виде строк);
    6. В каждый блок тела ответа промежуточная программа вносит некоторые изменения, а затем передает в соответствующей строке на сервер;.
    7. После обработки всех блоков, переданных приложением, промежуточная программа возвращает управление серверу, завершая работу с данным запросом.

Широкий шаг в направлении XHTML

Многие компонентные технологии являются сложными, поэтому лучшими примерами для понимания будут простые одноразовые бесполезные программы. Но это не относится к WSGI, и, по существу, я предложу вам весьма практический пример. Многие разработчики предпочитают использовать web-страницы в формате XHTML, потому что проще управлять технологиями XML, чем возиться с тэгами HTML, и последние тенденции в интернете способствуют появлению сайтов, которые проще считывать автоматизированными средствами. Проблема заключается в том, что не все браузеры корректно поддерживают XHTML. Листинг 1 (safexhtml.py) - это модуль промежуточного программного обеспечения WSGI, который проверяет входящие запросы, чтобы убедиться, что браузер поддерживает XHTML, и, если это не так, транслирует ответы XHTML в чистый HTML. Если вы используете такой модуль, то все ваши основные приложения могут продуцировать код XHTML, а промежуточное программное обеспечение при необходимости позаботится о трансляции в HTML. Внимательно изучите листинг 1 и попробуйте объединить его с общей схемой выполнения промежуточной программы из предыдущего раздела. В листинге приводится много примечаний, чтобы вы могли индентифицировать различные стадии выполнения этой программы.

Листинг 1 (safexhtml.py). Промежуточное обеспечение WSGI для трансляции XHTML в HTML для тех браузеров, которые не могут обрабатывать этот формат
import cStringIO
from itertools import chain
from xml import sax
from Ft.Xml import CreateInputSource
from Ft.Xml.Sax import SaxPrinter
from Ft.Xml.Lib.HtmlPrinter import HtmlPrinter

XHTML_IMT = "application/xhtml+xml"
HTML_CONTENT_TYPE = 'text/html; charset=UTF-8'


#Этот класс не специфичен для примера 
промежуточной программы 
#и может быть использован "как есть" в
 других реализациях промежуточных программ WSGI
#Он является частью библиотеки wsgi.xml 
(http://uche.ogbuji.net/tech/4suite/wsgixml)
#Вы можете установить ее при помощи easy_
install wsgixml и затем использовать
#из wsgixml.util import import iterwrapper
class iterwrapper:
    """
    Упаковывает итератор тела ответа от
 приложения, для соответствия
    -требованиям WSGI.
    """
    def __init__(self, wrapped, response_chunk_handler):
        """
        wrapped - итератор, получаемый из приложения
        response_chunk_handler - вызываемая 
функция для любой обработки
            части тела ответа перед передачей на сервер.
        """
        self._wrapped = wrapped
        self._response_chunk_handler = response_chunk_handler
        if hasattr(wrapped, 'close'):
            self.close = self._wrapped.close

    def __iter__(self):
        return self

    def next(self):
        return self._response_chunk_handler(self._wrapped.next())


class safexhtml(object):
    """
    Промежуточная программа, которая проверяет 
наличие средств обработки XHTML у клиента и транслирует
    XHTML в HTML, если клиент не может обрабатывать XHTML
    """
    def __init__(self, app):
        #Фаза запуска
        self.wrapped_app = app
        return

    def __call__(self, environ, start_response):
        #Обработка фазы ответа клиента.
        #Вызывается для каждого запроса клиента, 
проходящего через промежуточное ПО

        #Сообщает ли клиент явно, что он поддерживает XHTML?
        #Обратите внимание, что сообщая об этом, он принимает*/*
 или приложение/*не будет достаточно
        xhtml_ok = XHTML_IMT in environ.get('HTTP_ACCEPT', '')

        #Специальная функция start_response для 
этой промежуточной программы
        def start_response_wrapper(status, response_headers, exc_info=None):
            #Предположим, что ответ - не XHTML; 
тогда трансформацию не активируем
            environ['safexhtml.active'] = False
            #Проверяем тип контента для ответа, 
чтобы убедиться, что это XHTML
            #который нужно преобразовать
            в имя, значение в response_headers:
                #значение content-type - media type, описанный как
                #media-type = type "/" subtype *( ";" parameter )
                if ( name.lower() == 'content-type'
                     and value.split(';')[0] == XHTML_IMT ):
                    #Извлекаем content-length, если имеется,
 (значение должно быть
                    #пересчитано сервером)
                    #Также извлекаем content-type,
 который ниже будет заменен
                    response_headers = [ (name, value)
                        на имя, значение в response_headers
                            if ( name.lower()
                                 not in ['content-length', 'content-type'])
                    ]
                    #Помещаем в обновленный тип контента
                    response_headers.append
(('content-type', HTML_CONTENT_TYPE))
                    #Ответ XHTML, поэтому активируем преобразование
                    environ['safexhtml.active'] = True
                    break

            #Мы игнорируем значение, возвращенное 
функцией start_response
            start_response(status, response_headers, exc_info)
            #Заменяем любую вызываемую функцию write() 
callable фиктивным значением, которое вызывает ошибку
            #Идея заключается в том, чтобы отклонить
 поддержку приложений, которые используют write()
            def dummy_write(data):
                raise RuntimeError('safexhtml does not support the deprectated 
                                                  write() callable in WSGI clients')
            return dummy_write

        #Получаем итератор от приложения, которое выдаст 
       #фрагменты тела ответа
        iterable = self.wrapped_app(environ, start_response_wrapper)

        #Собираем строку вывода для концентрации
        #(используется только в том случае, если требуется трансляция в HTML)
        response_blocks = []

        #Эта функция обрабатывает каждый фрагмент
 вывода (простая строка) от
        #приложения, возвращая измененный фрагмент
 для передачи на сервер
        def handle_response_chunk(chunk):
            if xhtml_ok:
                #Клиент может обрабатывать XHTML, поэтому
 промежуточному ПО не приходится ничего делать
                #Обратите внимание, что передается 
первоначальная функция start_response
                #а не возвращенный функцией этого 
промежуточного ПО start_response_wrapper
                фрагмент
            else:
                if environ['safexhtml.active']:
                    response_blocks.append(chunk)
                    return '' #Соответствует правилам буферизации для WSGI
                else:
                    return chunk

        #После того, как приложение завершит отправку фрагментов
        #тела ответа, в том случае, если требуется трансляция HTML, необходимо
        #отправить дополнительный фрагмент с
 полностью транслированным XHTML
        #Это обрабатывается следующей функцией, генератором.
        #Если трансляция HTML не требуется, 
то генератор ничего не возвращает
        def produce_final_output():
            if not xhtml_ok and environ['safexhtml.active']:
                #Необходимо преобразовать ответ из XHTML в HTML 
                xhtmlstr = ''.join(response_blocks) #Сначала концентрируем ответ

                #Теперь воспользуемся 4Suite для преобразования XHTML в HTML
                htmlstr = cStringIO.StringIO()  #Удерижм результирующий HTML result
                parser = sax.make_parser(['Ft.Xml.Sax'])
                handler = SaxPrinter(HtmlPrinter(htmlstr, 'UTF-8'))
                parser.setContentHandler(handler)
                #Отказываемся от загрузки XHTML DTDs из интернета
                parser.setFeature(sax.handler.feature_external_pes, False)
                parser.parse(CreateInputSource(xhtmlstr))
                yield htmlstr.getvalue()

        return chain(iterwrapper(iterable, handle_response_chunk),
                     produce_final_output())

Класс safexhtml - это полная реализация промежуточного ПО. Каждый экземпляр является вызываемым объектом, поскольку класс описывает специальный метод __call__. Мы передаем экземпляр класса на сервер и одновременно передаем инкапсулируемое приложение инициализатору __init__. Инкапсулированное приложение может также быть еще одним экземпляром промежуточного ПО, если safexhtml связывается с другой промежуточной программой. Когда промежуточная программа вызывается в результате запроса к серверу, то класс сначала проверяет заголовки Accept, переданные клиентом, чтобы убедиться, содержат ли они официальный медиа-тип XHTML. Если это так (флаг xhtml_ok), то можно просто передать XHTML, и промежуточное ПО не будет иметь дела с этим запросом.

Если клиент не может обрабатывать XHTML, то класс описывает специальную вложенную функцию start_response_wrapper , обязанности которой заключаются в проверке заголовков ответа от приложения с целью убедиться, что формат ответа - XHTML. Если это так, что ответ необходимо транслировать в чистый HTML, этот факт помечается флагом safexhtml.active в этой конфигурации. Одна из причин использовать такую конфигурацию для флага - это то, что он собирает информацию о проблемах, передавая флаг обратно программе промежуточного ПО. Запомните, что start_response_wrapper вызывается асинхронно во время выбора приложения, и может вызвать трудности в управлении необходимым состоянием промежуточной программы.

Еще одна причина использовать эту конфигурацию - это необходимость сообщить стеку WSGI об изменении контента. Если тело ответа необходимо транслировать, то функция start_response_wrapper не только устанавливает флаг safexhtml.active, но также изменяет медиа-тип ответа на text/html и удаляет любой заголовок Content-Length, поскольку трансляция почти определенно изменит длину тела ответа, и его нужно будет пересчитать в сторону уменьшения, вероятно, это будет сделано сервером.

Приложения WSGI продуцируют тело ответа HTTP, передавая обратно итератор, который извлекает последовательность фрагментов простого текста для построения ответа. Инкапсулирующий класс iterwrapper обрабатывает каждый фрагмент в соответствии с правилами для промежуточного программного обеспечения и обеспечивает соблюдение правил WSGI. Например, если итератор из приложения имеет метод close, то сервер, а, следовательно, и эта промежуточная программа должны его вызвать.

iterwrapper как раз и обеспечивает такой порядок вещей. Вложенная функция handle_response_chunk выполняет большой объем работы по обработке каждого фрагмента приложения. Если требуется трансляция в HTML, то эта функция собирает фрагменты в список response_blocks. Для упрощения кода, safexhtml запускает механизм трансляции только для всего документа XHTML, который, возможно, нужно собрать из фрагментов, извлеченных приложением. Однако правилами WSGI оговаривается, что промежуточная программа должна передать на сервер какую-либо информацию при каждом извлечении фрагмента приложением. Достаточно передать пустую строку, именно это и делает функция handle_response_chunk. После того, как приложение завершит работу, функции safexhtml, возможно, потребуется передать дополнительный фрагмент, содержащий результаты трансляции в HTML. Это выполняет генератор produce_final_output, собирая тело ответа и пропуская его через код трансляции, в конце-концов извлекая весь вывод в виде одной строки. Функция itertools.chain используется для того, чтобы добавить этот заключительный фрагмент (если он существует) и отправить его серверу.

Листинг 2 (wsgireftest.py) - это серверная программа для тестирования промежуточного ПО. Она использует wsgiref, который включает очень простой сервер WSGI. Этот модуль входит в стандартную библиотеку Python 2.5.

Листинг 2 (wsgireftest.py). Серверная программа для тестирования программы из листинга 1
import sys
from wsgiref.simple_server import make_server
from safexhtml import safexhtml

XHTML = open('test.xhtml').read()
XHTML_IMT = "application/xhtml+xml"
HTML_IMT = "text/html"
PORT = 8000


def app(environ, start_response):
    print "using IMT", app.current_imt
    start_response('200 OK', [('Content-Type', app.current_imt)])
    #Swap the IMT used for response (alternate between XHTML_IMT and HTML_IMT)
    app.current_imt, app.other_imt = app.other_imt, app.current_imt
    return [XHTML]

app.current_imt=XHTML_IMT
app.other_imt=HTML_IMT

httpd = make_server('', PORT, safexhtml(app))
print 'Starting up HTTP server on port %i...'%PORT

    # Respond to requests until process is killed
httpd.serve_forever()

Листинг 2 считывает простой файл XHTML, представленный в листинге 3 (test.xhtml), и обслуживает его, изменяя медиа-типы. Программа использует стандартный медиа-тип XHTML для первого запроса, медиа-тип HTML для второго, снова XHTML для третьего и так далее. Здесь используется способность промежуточного программного обеспечения не трогать ответ, если он помечен как HTML.

Листинг 3 (test.xhtml). Простой файл XHTML используется тем же простым сервером из листинга 2
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
  <head>
    <title>Virtual Library</title>
  </head>
  <body>
    <p>Moved to <a href="http://vlib.org/">vlib.org</a>.</p>
  </body>
</html>

Вы должны увидеть действие этой промежуточной программы, если выполните листинг 2 и просмотрите его в браузере, умеющем работать с XHTML, например, Firefox а затем в браузере, испытывающем трудности с XHTML, например, в Microsoft Internet Explorer. Выполните запрос дважды для каждого браузера, чтобы увидеть действие медиа-типа ответа на работу промежуточной программы. Используйте команду View Source, чтобы просмотреть тело результирующего ответа и функцию Page Info, чтобы увидеть медиа-тип переданного ответа. Можно также протестировать пример при помощи инструмента командной строки для HTTP cURL: curl -H 'Accept: application/xhtml+xml,text/html' http://localhost:8000/ для эмуляции браузера, "понимающего" XHTML, и curl -H 'Accept: text/html' http://localhost:8000/, чтобы эмулировать противоположный случай. Если вы хотите просмотреть заголовки ответа, используйте параметр -D <filename> и проверяйте данное имя файла после каждого вызова cURL.


Краткое заключение

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

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

Ресурсы

Научиться

  • Оригинал статьи Mix and match Web components with Python WSGI;
  • Сайт сообщества WSGI: здесь вы найдете все, что хотели узнать о WSGI. Вам точно не придется читать всю спецификацию по WSGI (PEP 333);
  • Инфраструктура Zend: если вы разрабатываете программы на PHP, узнайте об этой новой инфраструктуре с открытым исходным кодом для разработки web-приложений и сервисов;
  • XHTML, step-by-step (XHTML шаг за шагом) Уче Огбуйи (Uche Ogbuji), сайт developerWorks, сентябрь 2005 г.): из этого практического руководства вы больше узнаете о XHTML, в том числе, о некоторых проблемах разработчиков;
  • Sockets programming in Python (Программирование сокетов на языке Python) (Харипрасад Неллитеертха (Hariprasad Nellitheertha), сайт developerWorks, октябрь 2005 г.): изучите базовый API для разработки сокетов, а также модуль, который упрощает разработку сервера сокета, а затем создайте простой сервер для чата при помощи этих методов;
  • Charming Python: (Доктор Дэвид Мертц (David Mertz), сайт developerWorks): получите дополнительную информацию о передовых методах программирования на языке Phyton;
  • Discover Python: (Роберт Бруннер (Robert Brunner), сайт developerWorks): узнайте все о языке Python;
  • "Python Web frameworks, Part 1: Develop for the Web with Django and Python" (Web-инфраструктура Python, часть 1: разработка для web при помощи Django и Python) и "Python Web frameworks, Part 2: Web development with TurboGears and Python" (Web-инфраструктура Python, часть 2: разработка для web при помощи TurboGears и Python) (Иан Маурер (Ian Maurer), сайт developerWorks, июнь-июль 2006 г.): начните ваше знакомство с web-инфраструктурой Python с чтения этой статьи;
  • Раздел Web development сайта developerWorks : углубите ваши знания по разработке сайтов при помощи статей и практических руководств, посвященных web-технологиям.

Получить продукты и технологии

  • 4Suite: получите приложение, которое использовалось в примере, приведенном в нашей статье, для преобразования XHTML в HTML. Автор является ведущим разработчиком пакета 4Suite. Самый простой способ получить этот пакет - воспользоваться файлом easy_install и запустить его с параметром easy_install 4Suite;
  • cURL: получите замечательный инструмент для web-тестирования и интеграции сценариев;
  • Справочная библиотека WSGI Reference Library (wsgiref): входит в состав версии Python 2.5, но если вы используете Python 2.4, то самый простой способ получить ее - это воспользоваться файлом easy_install и запустить его с параметром easy_install wsgiref. Получите документацию на модуль на сайте Python 2.5 documentation sandbox. wsgiref поставляется также с модулем под названием validate, который позволяет проверить соответствие вашего кода WSGI;
  • WebSphere Application Server Version 6.0: загрузите пробную бесплатную версию;
  • IBM: пробное программное обеспечение: создайте свой следующий проект разработки при помощи программного обеспечения, которое можно загрузить непосредственно с сайта developerWorks.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Open source, Web-архитектура
ArticleID=192674
ArticleTitle=Смешивание и подгонка web-компонентов при помощи интерфейса Python WSGI
publish-date=01292007