Сайт на python: CGI: пишем простой сайт на Python. Часть 1: Hello world

Содержание

CGI: пишем простой сайт на Python. Часть 1: Hello world

Проще всего создать динамические страницы на Python при помощи CGI-скриптов. CGI-скрипты — это исполняемые файлы, которые выполняются веб-сервером, когда в URL запрашивается соответствующий скрипт.

Сегодня я расскажу про то, как написать Hello world, как CGI-скрипт.

Настройка локального сервера

В Python уже есть встроенный CGI сервер, поэтому его настройка элементарна.

Для запуска из консоли (для любителей linux-систем). Запускать нужно из той папки, где мы хотим работать:

python3 -m http.server --cgi

Для сидящих на Windows чуть проще будет запуск Python файла (заметьте, что он должен находиться в той же папке, в которой мы планируем работать!):

from http.server import HTTPServer, CGIHTTPRequestHandler
server_address = ("", 8000)
httpd = HTTPServer(server_address, CGIHTTPRequestHandler)
httpd.serve_forever()

Теперь откройте браузер и в адресной строке наберите localhost:8000

Если у вас примерно такая же картина, значит, у вас все заработало!

Hello world

Теперь в той папке, где мы запустили сервер, создаём папку cgi-bin (у меня она уже создана).

В этой папке создаём скрипт hello.py со следующим содержимым:

#!/usr/bin/env python3

print("Content-type: text/html")
print()
print("<h2>Hello world!</h2>")

Первая строка говорит о том, что это Python скрипт (CGI-скрипты можно не только на Python писать).

Вторая строка печатает заголовок. Он обозначает, что это будет html файл (бывает ещё css, javascript, pdf и куча других, и браузер различает их по заголовкам).

Третья строка (просто символ новой строки) отделяет заголовки от тела ответа.

Четвёртая печатает Hello world.

Теперь переходим на localhost:8000/cgi-bin/hello.py

И радуемся!

Если у вас не работает, проверьте, установлены ли права на выполнение.

Также в консоли запущенного сервера появляются сообщения об ошибках. Например, убрал скобочку и обновил страницу:

В следующей части мы рассмотрим обработку данных форм и cookies.

10 популярных сайтов, созданных на языке Python

Вообще в интернете десятки тысяч сайтов, созданных на основе Python. Этот мощный язык программирования разработал Гвидо ван Россум, а произошло это еще в 1991 году. Сегодня Python популярен как среди начинающих, так и среди опытных разработчиков.

Многие наиболее успешные технологические компании выбирают Python для создания бэкенда своих продуктов. Давайте рассмотрим десятку знаменитых сайтов, при разработке которых использовался (и продолжает использоваться) Python.

Instagram — это крупнейшее в мире приложение для обмена фотографиями. А для бэкенда там используется Python. По словам разработчиков этой платформы, Instagram в настоящее время это показательный пример использования фреймворка Django, а ведь он написан полностью на Python.

Google это самый широко используемый поисковик в мире. Он занимает больше 75% рынка. Алекс Мартелли, инженер, уже давно работающий в этой компании, рассказал, почему они начали использовать Python в своем техническом стеке:

«Это пошло, как мне кажется, еще от самых первых «гуглеров» (Сергея, Ларри, Крейга,…), принявших очень хорошее инженерное решение: «Python — везде, где это возможно, C++ — где необходимо»».

Spotify — это стриминговый сервис, позволяющий прослушивать отдельные музыкальные треки или целые альбомы практически без задержки (благодаря заблаговременной буферизации). Приложение Spotify было выпущено в 2008 году, а в настоящее время оно имеет больше 113 миллионов платных подписчиков.

Хотя сайт Spotify построен на WordPress, приложение создавалось на Python. Один из разработчиков, Джефф ван дер Меер, объясняет, почему команда Spotify использовала именно этот язык для бэкенда приложения:

«Бэкенд Spotify состоит из большого количества независимых сервисов. И примерно 80% этих сервисов написаны на Python».

Netflix — крупнейшая телевизионная сеть в мире. Фильмы и сериалы на этой платформе смотрят 167 миллионов людей из более чем 190 стран. Как написано в технологическом блоге компании,

«Разработчики Netflix вольны выбирать технологии, наиболее подходящие для решения их задач. И все больше разработчиков обращаются к Python. Этому способствует богатство стандартной библиотеки, сжатый, понятный и при этом выразительный синтаксис, многочисленное сообщество и обилие сторонних библиотек, которыми в любой момент можно воспользоваться для решения насущной задачи».

При помощи Uber, сервиса для поиска попутчиков, происходит больше 15 миллионов поездок ежедневно. По словам разработчиков приложения Uber, на более низких уровнях они преимущественно пишут на Python, Node.js, Go и Java. Начинали они с двух основных языков: Node.js для команды Marketplace и Python для всех остальных. Сегодня эти два первых языка по-прежнему используются для большинства сервисов Uber.

Dropbox — это тихая гавань для ваших фотографий, документов, видео и всяких других файлов.

Вам когда-нибудь было любопытно, как приложению вроде Dropbox удалось масштабироваться от 2000 до 200 миллионов пользователей? При разработке серверов этой компании Python используется буквально повсеместно. И это неудивительно: с начала 2013 и до октября 2019 года в Dropbox работал Гвидо ван Россум, создатель языка Python.

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

«На прикладном уровне мы используем Python и очень сильно модифицированный Django. А что касается веб-серверов — используем Tornado и Node.js»

, — Пол Скьяра, соучредитель Pinterest.

Instacart — компания, осуществляющая быструю доставку продуктов из магазинов. Приложение этой компании является одним из самых популярных в данном сегменте: им пользуются больше 500 тысяч людей.

«У нас есть команда специалистов по Data Science, они работают на R и Python. Код, написанный на этих языках, используется, например, для прогнозирования: предварительных оценок, чтения данных, прикидок, сколько закупщиков нам понадобится в следующие пару недель и т. п.», — команда разработчиков Instacart.

У этого сайта 330 миллионов активных пользователей.

«Самое важное, что побуждает нас использовать Python?.. собственно, есть два основных довода в его пользу. Во-первых, это библиотеки. Во-вторых (и это важнее) — его легкость для чтения и написания кода. Когда мы нанимаем новых сотрудников, я предупреждаю, что все, что они пишут, должно быть на Python — чтобы я смог прочесть. И это круто. Я могу просто проходить через комнату и, глянув на экран, понять, хороший код у человека или нет. Потому что у хорошего кода на Python очень понятная структура. Это весьма облегчает мою жизнь»

, — из интервью со Стивом Хаффманом и Алексисом Оганяном (соучредителями Reddit) на PyCon.

В США Lyft это самый быстрорастущий сервис для поиска попутчиков. Компания работает в больше чем 200 городах, с ее участием происходит 14 миллионов поездок в месяц.

На митапе в Сан-Франциско в 2018 году разработчик из Lyft, Рой Вильямс, рассказал:

«Lyft — большой поклонник Python. Обычно в сервисах используются NumPy, Pandas и PuLP для обработки запросов через Flask, Gevent и Gunicorn. Для борьбы с мошенничеством мы используем SciPy».

Создаём веб при помощи Python | GeekBrains

Краткий ликбез о применении одного из самых популярных языков программирования.

https://d2xzmw6cctk25h.cloudfront.net/post/1061/og_cover_image/72a0f9b9d3738d395314c67e2a090fd8

Пускай это прозвучит немного пафосно, но мы живём в золотой век веб-разработки. Веб-технологии никогда не были такими изысканными и гибкими, как сегодня. Если вы хотите создать качественный веб-сайт или веб-приложение, вы без труда найдёте массу инструментов для реализации любых своих задумок. И один из них — Python.

Вопреки распространенному мнению, Python полезен не только для обработки данных и скриптов. Посмотрите на рейтинг портала HotFrameworks.com, и вы увидите, что пятый по популярности веб-фреймворк создан для работы с Python.

Python и веб-разработка

При разработке веб-приложения Python в основном используется для обработки бэк-энд и маршрутизации, где в роли конкурентов у него PHP и Ruby. Веб-страницы все равно необходимо отображать с использованием HTML и CSS, а функциональная часть фронтэнда по-прежнему выполняется на JavaScript. Если вам интересен этот язык, то рекомендуем начать его изучения с бесплатного интенсива по основам Python.

В зависимости от того, какой фреймворк Python вы используете, взаимодействия могут существенно упрощаться. Например, Django имеет систему шаблонов для написания специальных HTML-файлов, которые могут вставлять код Python и взаимодействовать с данными из бэк-энда.

Такой тип взаимодействия называется full-stack фреймворком. С его помощью вы можете работать с системами, обрабатывающими HTTP-запросы, хранилищами баз данных, шаблонами веб-страниц, запросами маршрутизации и т. д. С другой стороны, есть и не full-stack фреймворки, которые также называют микрофреймворками, которые обрабатывают только базовую логику. А для сторонних работ они должны быть объединены со сторонними базами данных, шаблонизаторами и т. д.

В общем, full-stack фреймворки имеют более крутые кривые обучения и заставляют вас принимать множество решений относительно структуры, но предоставляют все, что вам нужно. Микрофреймворки могут быть изучены в кратчайшие сроки и являются более гибкими, но вам, скорее всего, каждый раз придётся изобретать велосипед.

Python против других языков

Если вы следите за текстами в нашем блоге, то уже имеете представление о популярных JavaScript-фреймворках, например, React или Angular. Они стремительно развиваются, особенно среди новичков. Многие думают: «Если мне нужен JavaScript для внешнего интерфейса, почему бы не использовать JavaScript для back-end?» И это действительно имеет смысл. А взгляните на PHP — он существует уже много десятилетий, его окружает большое количество документации, он востребован. Тоже вполне себе логичный вариант для back-end.

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

Но отказаться от Python вам будет очень непросто, ведь для любви к нему есть минимум 5 причин.

Python и фреймворки

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

Django — пожалуй, самый известный и популярный фреймворк для веб-разработки с использованием Python. Он поставляется с десятками встроенных модулей, прекрасно собранных и безупречно взаимодействующих друг с другом. Сначала вам потребуется немного времени, чтобы понять алгоритм создания веб-приложений, освоить внутренние структуры на Django. Но как только вы поймёте что к чему, быстрая разработка не станет проблемой. И да, если вы хотите работать веб-разработчиком на Python, знание Django — часто единственный путь.

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

Flask — микрофреймворк, в некотором роде являющийся полном противоположностью Django. Он будет прост и понятен новичку, но обеспечит лишь базовый уровень возможностей, в то время как основную функциональность на себя должны будут взять сторонние интегрированные компоненты. Соответственно полного погружения в предмет Flask вам не подарит, лишь общее представление.

То есть если вы знаете, как и что вам необходимо использовать для реализации задумки, то Flask может стать тем минимальным клеем, что соберёт все воедино. Но если у вас нет ни опыта работы, ни понимания того, как должно функционировать будущее приложение, то Flask — далеко не лучший выбор.

Pyramid — это некий компромиссе между Django и Flask. Данный фреймворк не так функционален, как Django, и не так упрям, как Flask, но прост, удобен и вполне достаточен для организации большинства веб-приложений. Здесь есть большая библиотека официальных и неофициальных плагинов, с помощью которых вы сможете реализовать все задумки для вашего проекта.

Python и реальная жизнь

Если вы дочитали текст до данного раздела, то наверняка хотите увидеть реальные примеры веб-применения Python. Что ж, загибайте пальцы или открывайте новые закладки, кому как удобно: YouTube, Instagram, DropBox, Google, Reddit, Pinterest, FireFox, NASA, Quora и многие-многие другие. Да, где-то Python используется лишь частично, где-то и вовсе его стараются заменять более новыми языками, но влияние на веб у змеиного языка по-прежнему очень велико.

Python и обучение

Теперь остаётся лишь один вопрос: «Где обучиться?». С этим, к счастью, на нашем портале проблем никаких. Хотите — приобретайте целую профессию «Программист Python», хотите лишь отдельный курс «Python. Уровень 1» или «Python. Уровень 2», а хотите просто заручитесь помощью хорошей книги, например из списка «8 книг по Python для начинающих».

Текст основан на статье «Python on the Web: The Amazing Things You Can Build».

Как создавать сайты в Python?

Python очень легкий язык программирования с низким порогом вхождения. Те программисты которые уже знают любой другой язык программирования будь то PHP, Java или C подобные языки, то понимание языка Python будет намного выше. Ассоциируя уже имеющие знания другого языка программирования с новыми функциями и модулями Python, вы легко смоете понять логику работы Python. В сравнении с PHP, Python не выполняет только одну задачу. Он применяется в разных отраслях, таких как создание программ, приложений в смарфоне, игр и сайтов.

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

Делать сайты на Python перспективнее?

Да. PHP ограничен одними сайтами и развивается в сторону веб (для чего он и был создан). Python в свою очередь, развивается в разные стороны, это даст вам шанс в будущем сменить свою работу и начать делать, например, программы вместо сайтов не меняя язык программирования. Вам не придется изучать опять новый язык программирования чтобы сменить род деятельности т.е. перескочить с сайтостроения на написание приложении для android, apple, symbian и т.д.

Еще один плюс в сторону Python в том, что он строго типизирован как и Java. Этот язык обучит вас хорошим манерам программиста и не даст волю творить хаос в коде. Но, не будем все обобщать, творить бессмыслицу можно и на Python и делать шедевры на том же PHP. Python научит разделать код на логические блоки чтобы понимать где зона выполнения цикла, где заканчивается один IF и начинается другой и т.д. На PHP тоже можно структурировать код на логические блоки, но там это не обязательно, следовательно новичок может написать код в одну строку и ему ничего не будет, в момент когда Python новичок получит ошибку и начнет править код.

С чего начать создание сайтов на Python?

Если вы хотите создать сайт на HTML то для этого Python вам не нужен, достаточно купить любой хостинг и загрузить файлы сайта. В случае если у вас более серьезные планы и динамические планы на свой сайт то нужно определится с выбором python фреймворка для создания сайта. Небольшой список фреймворков: Django, Pylons, TurboGears, Twisted, CherryPy. Мы остановимся на Django т.к. на данный момент он является самым популярным фреймворком для создании сайтов на Python.

Почему выбрать Django?

Хорошая документация — документация данного фреймворка выполнена на высшем уровне. Все статьи написаны понятным языком и снабжены примерами и объяснениями которые не освятят ни единого вопроса. Есть даже книги на русском языке по данному фреймворку которые занимают лидирующие места продаж в своем разделе.

Самостоятельная генерация админ панели — Это пожалуй самая уникальная сторона Django по сравнению с другими фреймворками а том же PHP. Данная возможность поможет вам выиграть во времени написания сайта т.к. создание админ интерфейса сводится наброску нужных моделей и можно уже начать работать с сайтом.

Поддержка паттерна MTV (Model-Template-View) — он напоминает классический MVC. MTV разделяет бизнес логику от дизайна, что очень хорошо сказывается на будущее огромного проекта которого будет поддерживать несколько людей. Пока дизайнер будет разбираться каким цветом и шрифтом он выведет мета теги, меню сайта и текст то программист независимо от дизайнера, будет писать для сайта функционал. Это позволит увеличить КПД в работе сайта.

Да и работать в кругах программистов авторитетнее на Python, C#, Java. PHP хороший язык программирования он будет жить и занимать лидирующее место инструмента создании сайтов еще много лет, но вы же не хотите ограничивать свои возможности только на создании сайтов?

Создание сайта на Python

В рамках данной статьи мы разберем cоздание сайта на языке программирования Python. Естественно, есть масса конструкторов, позволяющих всего за несколько минут создавать подобные проекты, но собственная разработка наверняка будет полезным опытом для каждого.

Установка

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

В этом примере мы будем пользоваться Web.Python 0.37, но, если хотите вы можете воспользоваться и последней версией.

Необходимо распаковать и скопировать папку web в директорию, где находится ваше приложение, либо просто выполнить следующую команду:

python setup.py install

В некоторых UNIX-подобных системах эту команду нужно выполнить с правами администратора:

sudo python setup.py install

Есть и другой способ установки – через EasyInstall, выполнив команду:

sudo easy_install web.py

Основные моменты

Теперь нужно создать текстовый файл под названием code.py. Открываем его и пишем в нем такой код:

import web

Это нужно для загрузки модуля Web.Py, для которого мы и делали все описанные выше операции.

Далее нужно объяснить серверу, какая у нас URL-структура. Ниже пишем:

urls = ( 
   '/', 'index' 
)

Теперь, если войти в корень нашего сайта, загрузится страничка index. Но, пока у нас еще ничего не готово, это только начало.

Страницы сайта, запросы GET\POST

Большинство из вас уже прекрасно понимают, чем отличаются запросы GET и POST. GET передается в адресную строку, POST – в тело скрипта.

Надежный сервис doctorsmm.com готов предложить Вам выгодные цены на покупку подписчиков в Инстаграме. Здесь, при заказе, Вы сможете выбрать любое качество добавляемых аккаунтов, а также скорость их поступления на профиль. К тому же на сайте действует таргетинг аудитории по географическим критериям. Торопитесь, пока предложение еще актуально!

Отметим еще один момент – передавать вручную POST-запросы без скриптов и форм – это тоже, что тягать кота за хвост, чтобы согнать его с дивана, вместо того, чтобы просто взять и переместить его куда надо.

На данном этапе необходимо создать класс index, который будет предусматривать главную страницу нашего сайта, или игры, смотря какой проект вы реализуете.

class index: 
   def GET(self): 
   return "Hello, world!"

Теперь, если зайти на сайт, отобразится текст Hello, world! Все как обычно.

Далее нужно сделать так, чтобы наше приложение выводило нам HTML-код сайта. Чтобы это сделать дописываем следующий код:

if __name__ == "__main__":   
   app = web.application(urls, globals()) 
   app.run()

В результате у нас получается такой вот код:

import web 
 
urls = ( 
    '/', 'index' 
) 
 
class index: 
    def GET(self): 
    return "Hello, world!" 
 
if __name__ == "__main__": 
    app = web.application(urls, globals()) 
    app.run()

Это скриптовая часть простейшего сайта, она уже готова, остался лишь запуск.

Запускаем сервер

Нужно войти в командную строку вашего сервера (либо SSH-терминала), где выполнить команду:

$ python code.py 
http://0.0.0.0:8080/

http://0.0.0.0:8080/ — адрес с портом нашего сайта. Его можно заменить на домен, если вы его уже прикрепили, локальный или внешний IP-адрес. Оттуда, собственно, мы и будем заходить на сайт. На этом первый этап создания сайта можно считать законченным. Далее нужно будет работать с шаблонизатором, базой данный и формами, но это уже темы для других статей.

Пишем веб сервис на Python с помощью FastAPI / Хабр

Знаю, знаю, наверное вы сейчас думаете «что, опять?!».

Да, на Хабре уже неоднократно писали о фреймворке FastAPI. Но я предлагаю рассмотреть этот инструмент немного подробнее и написать API своего собственного мини Хабра без кармы и рейтингов, зато с блэкджеком и с тестами, аутентификацией, миграциями и асинхронной работой с БД.

Схема базы данных и миграции


Прежде всего, с помощью SQLAlchemy Expression Language, опишем схему базы данных. Создадим файл models/users.py:
import sqlalchemy
from sqlalchemy.dialects.postgresql import UUID

metadata = sqlalchemy.MetaData()


users_table = sqlalchemy.Table(
    "users",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("email", sqlalchemy.String(40), unique=True, index=True),
    sqlalchemy.Column("name", sqlalchemy.String(100)),
    sqlalchemy.Column("hashed_password", sqlalchemy.String()),
    sqlalchemy.Column(
        "is_active",
        sqlalchemy.Boolean(),
        server_default=sqlalchemy.sql.expression.true(),
        nullable=False,
    ),
)


tokens_table = sqlalchemy.Table(
    "tokens",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column(
        "token",
        UUID(as_uuid=False),
        server_default=sqlalchemy.text("uuid_generate_v4()"),
        unique=True,
        nullable=False,
        index=True,
    ),
    sqlalchemy.Column("expires", sqlalchemy.DateTime()),
    sqlalchemy.Column("user_id", sqlalchemy.ForeignKey("users.id")),
)

И файл models/posts.py:
import sqlalchemy

from .users import users_table

metadata = sqlalchemy.MetaData()


posts_table = sqlalchemy.Table(
    "posts",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),
    sqlalchemy.Column("user_id", sqlalchemy.ForeignKey(users_table.c.id)),
    sqlalchemy.Column("created_at", sqlalchemy.DateTime()),
    sqlalchemy.Column("title", sqlalchemy.String(100)),
    sqlalchemy.Column("content", sqlalchemy.Text()),
)

Чтобы автоматизировать миграции базы данных, установим alembic:
$ pip install alembic

Для инициализации Alembic выполним:
$ alembic init migrations

Эта команда создаст в текущей директории файл alembic.ini и каталог migrations содержащий:
  • каталог versions, в котором будут хранится файлы миграций
  • скрипт env.py, запускающийся при вызове alembic
  • файл script.py.mako, содержащий шаблон для новых миграций.

Укажем url нашей базы данных, для этого в файле alembic.ini добавим строчку:
sqlalchemy.url = postgresql://%(DB_USER)s:%(DB_PASS)[email protected]%(DB_HOST)s:5432/%(DB_NAME)s

Формат %(variable_name)s позволяет нам устанавливать разные значения переменных в зависимости от среды окружения, переопределяя их в файле env.py например вот так:
from os import environ
from alembic import context
from app.models import posts, users

# Alembic Config объект предоставляет доступ
# к переменным из файла alembic.ini
config = context.config

section = config.config_ini_section
config.set_section_option(section, "DB_USER", environ.get("DB_USER"))
config.set_section_option(section, "DB_PASS", environ.get("DB_PASS"))
config.set_section_option(section, "DB_NAME", environ.get("DB_NAME"))
config.set_section_option(section, "DB_HOST", environ.get("DB_HOST"))

fileConfig(config.config_file_name)

target_metadata = [users.metadata, posts.metadata]

Здесь мы берем значения DB_USER, DB_PASS, DB_NAME и DB_HOST из переменных окружения. Кроме этого, в файле env.py указываются метаданные нашей базы в атрибуте target_metadata, без этого Alembic не сможет определить какие изменения необходимо произвести в базе данных.

Все готово и мы можем сгенерировать миграции и обновить БД:


$ alembic revision --autogenerate -m "Added required tables"
$ alembic upgrade head

Запускаем приложение и подключаем БД


Создадим файл main.py:
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

И запустим приложение, выполнив команду:
$ uvicorn main:app --reload

Убедимся, что все работает как надо. Открываем в браузере http://127.0.0.1:8000/ и видим
{"Hello": "World"}

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

Настроим startup и shutdhown события нашего сервиса, при которых будут происходить подключение и отключение от базы данных. Отредактируем файл main.py:

from os import environ

import databases

# берем параметры БД из переменных окружения
DB_USER = environ.get("DB_USER", "user")
DB_PASSWORD = environ.get("DB_PASSWORD", "password")
DB_HOST = environ.get("DB_HOST", "localhost")
DB_NAME = "async-blogs"
SQLALCHEMY_DATABASE_URL = (
    f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}"
)
# создаем объект database, который будет использоваться для выполнения запросов
database = databases.Database(SQLALCHEMY_DATABASE_URL)


app = FastAPI()


@app.on_event("startup")
async def startup():
    # когда приложение запускается устанавливаем соединение с БД
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    # когда приложение останавливается разрываем соединение с БД
    await database.disconnect()


@app.get("/")
async def read_root():
    # изменим роут таким образом, чтобы он брал данные из БД
    query = (
        select(
            [
                posts_table.c.id,
                posts_table.c.created_at,
                posts_table.c.title,
                posts_table.c.content,
                posts_table.c.user_id,
                users_table.c.name.label("user_name"),
            ]
        )
        .select_from(posts_table.join(users_table))
        .order_by(desc(posts_table.c.created_at))
    )
    return await database.fetch_all(query)

Открываем http://127.0.0.1:8000/ и если видим в ответе пустой список [], значит все прошло хорошо и можно двигаться дальше.

Валидация запроса и ответа


Реализуем возможность регистрации пользователей. Для этого нам понадобиться валидировать HTTP запросы и ответы. Для решения этой задачи воспользуемся библиотекой pydantic:
pip install pydantic

Создадим файл schemas/users.py и добавим модель, отвечающую за валидацию тела запроса:
from pydantic import BaseModel, EmailStr

class UserCreate(BaseModel):
    """ Проверяет sign-up запрос """
    email: EmailStr
    name: str
    password: str

Обратите внимание, что типы полей определяются с помощью аннотации типов. Помимо встроенных типов данных, таких как int и str, pydantic предлагает большое количество типов, обеспечивающих дополнительную проверку. Например, тип EmailStr проверяет, что полученное значение — корректный email. Для использования типа EmailStr необходимо установить модуль email-validator:
pip install email-validator

Тело ответа должно содержать свои собственные специфические поля, например id и access_token, поэтому добавим в файл schemas/users.py модели, отвечающие за формирование ответа:
from typing import Optional
from pydantic import UUID4, BaseModel, EmailStr, Field, validator


class UserCreate(BaseModel):
    """ Проверяет sign-up запрос """
    email: EmailStr
    name: str
    password: str


class UserBase(BaseModel):
    """ Формирует тело ответа с деталями пользователя """
    id: int
    email: EmailStr
    name: str


class TokenBase(BaseModel):
    token: UUID4 = Field(..., alias="access_token")
    expires: datetime
    token_type: Optional[str] = "bearer"

    class Config:
        allow_population_by_field_name = True

    @validator("token")
    def hexlify_token(cls, value):
        """ Конвертирует UUID в hex строку """
        return value.hex


class User(UserBase):
    """ Формирует тело ответа с деталями пользователя и токеном """
    token: TokenBase = {}

Для каждого поля модели можно написать кастомный валидатор. Например, hexlify_token преобразует UUID значение в hex строку. Стоит отметить, что вы можете использовать класс Field, когда нужно переопределить стандартное поведение поля модели. Например, token: UUID4 = Field(…, alias=«access_token») устанавливает псевдоним access_token для поля token. Для обозначения, что поле обязательно, в качестве первого параметра передается специальное значение — (ellipsis).

Добавим файл utils/users.py, в котором создадим методы, необходимые для записи пользователя в БД:

import hashlib
import random
import string
from datetime import datetime, timedelta
from sqlalchemy import and_

from app.models.database import database
from app.models.users import tokens_table, users_table
from app.schemas import users as user_schema

def get_random_string(length=12):
    """ Генерирует случайную строку, использующуюся как соль """
    return "".join(random.choice(string.ascii_letters) for _ in range(length))


def hash_password(password: str, salt: str = None):
    """ Хеширует пароль с солью """
    if salt is None:
        salt = get_random_string()
    enc = hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), 100_000)
    return enc.hex()


def validate_password(password: str, hashed_password: str):
    """ Проверяет, что хеш пароля совпадает с хешем из БД """
    salt, hashed = hashed_password.split("$")
    return hash_password(password, salt) == hashed


async def get_user_by_email(email: str):
    """ Возвращает информацию о пользователе """
    query = users_table.select().where(users_table.c.email == email)
    return await database.fetch_one(query)


async def get_user_by_token(token: str):
    """ Возвращает информацию о владельце указанного токена """
    query = tokens_table.join(users_table).select().where(
        and_(
            tokens_table.c.token == token,
            tokens_table.c.expires > datetime.now()
        )
    )
    return await database.fetch_one(query)


async def create_user_token(user_id: int):
    """ Создает токен для пользователя с указанным user_id """
    query = (
        tokens_table.insert()
        .values(expires=datetime.now() + timedelta(weeks=2), user_id=user_id)
        .returning(tokens_table.c.token, tokens_table.c.expires)
    )

    return await database.fetch_one(query)


async def create_user(user: user_schema.UserCreate):
    """ Создает нового пользователя в БД """
    salt = get_random_string()
    hashed_password = hash_password(user.password, salt)
    query = users_table.insert().values(
        email=user.email, name=user.name, hashed_password=f"{salt}${hashed_password}"
    )
    user_id = await database.execute(query)
    token = await create_user_token(user_id)
    token_dict = {"token": token["token"], "expires": token["expires"]}

    return {**user.dict(), "id": user_id, "is_active": True, "token": token_dict}

Создадим файл routers/users.py и добавим sign-up роут, указав, что в запросе он ожидает модель CreateUser и возвращает модель User:

from fastapi import APIRouter
from app.schemas import users
from app.utils import users as users_utils


router = APIRouter()


@router.post("/sign-up", response_model=users.User)
async def create_user(user: users.UserCreate):
    db_user = await users_utils.get_user_by_email(email=user.email)
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    return await users_utils.create_user(user=user)

Осталось только подключить роуты из файла routers/users.py. Для этого добавим в main.py следующие строки:
from app.routers import users
app.include_router(users.router)

Аутентификация и контроль доступа


Теперь, когда в нашей базе данных есть пользователи, все готово для того чтобы настроить аутентификацию приложения. Добавим эндпоинт, который принимает имя пользователя и пароль и возвращает токен. Обновим файл routers/users.py, добавив в него:
from fastapi import Depends
from fastapi.security import OAuth3PasswordRequestForm


@router.post("/auth", response_model=users.TokenBase)
async def auth(form_data: OAuth3PasswordRequestForm = Depends()):
    user = await users_utils.get_user_by_email(email=form_data.username)

    if not user:
        raise HTTPException(status_code=400, detail="Incorrect email or password")

    if not users_utils.validate_password(
        password=form_data.password, hashed_password=user["hashed_password"]
    ):
        raise HTTPException(status_code=400, detail="Incorrect email or password")

    return await users_utils.create_user_token(user_id=user["id"])

При этом, нам не нужно самостоятельно описывать модель запроса, Fastapi предоставляет специальный dependency класс OAuth3PasswordRequestForm, который заставляет роут ожидать два поля username и password.

Чтобы ограничить доступ к определенным роутам для неаутентифицированных пользователей, напишем метод-зависимость(dependency). Он проверит, что предоставленный токен принадлежит активному пользователю и вернет данные пользователя. Это позволит нам использовать информацию о пользователе во всех роутах, требующих аутентификации. Создадим файл utils/dependecies.py:

from app.utils import users as users_utils
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth3PasswordBearer


oauth3_scheme = OAuth3PasswordBearer(tokenUrl="/auth")


async def get_current_user(token: str = Depends(oauth3_scheme)):
    user = await users_utils.get_user_by_token(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid authentication credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )
    if not user["is_active"]:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="Inactive user"
        )
    return user

Обратите внимание, что зависимость может в свою очередь зависеть от другой зависимости. К пример OAuth3PasswordBearer — зависимость, которая дает понять FastAPI, что текущий роут требует аутентификации.

Чтобы проверить, что все работает как надо, добавим роут /users/me, возвращающий детали текущего пользователя. В файл routers/users.py добавим строки:

from app.utils.dependencies import get_current_user


@router.get("/users/me", response_model=users.UserBase)
async def read_users_me(current_user: users.User = Depends(get_current_user)):
    return current_user

Теперь у нас есть роут /users/me к которому имеют доступ только аутентифицированные пользователи.

Все готово для того, чтобы наконец добавить возможность пользователям создавать и редактировать публикации:

utils/posts.py
from datetime import datetime

from app.models.database import database
from app.models.posts import posts_table
from app.models.users import users_table
from app.schemas import posts as post_schema
from sqlalchemy import desc, func, select


async def create_post(post: post_schema.PostModel, user):
    query = (
        posts_table.insert()
        .values(
            title=post.title,
            content=post.content,
            created_at=datetime.now(),
            user_id=user["id"],
        )
        .returning(
            posts_table.c.id,
            posts_table.c.title,
            posts_table.c.content,
            posts_table.c.created_at,
        )
    )
    post = await database.fetch_one(query)

    # Convert to dict and add user_name key to it
    post = dict(zip(post, post.values()))
    post["user_name"] = user["name"]
    return post


async def get_post(post_id: int):
    query = (
        select(
            [
                posts_table.c.id,
                posts_table.c.created_at,
                posts_table.c.title,
                posts_table.c.content,
                posts_table.c.user_id,
                users_table.c.name.label("user_name"),
            ]
        )
        .select_from(posts_table.join(users_table))
        .where(posts_table.c.id == post_id)
    )
    return await database.fetch_one(query)


async def get_posts(page: int):
    max_per_page = 10
    offset1 = (page - 1) * max_per_page
    query = (
        select(
            [
                posts_table.c.id,
                posts_table.c.created_at,
                posts_table.c.title,
                posts_table.c.content,
                posts_table.c.user_id,
                users_table.c.name.label("user_name"),
            ]
        )
        .select_from(posts_table.join(users_table))
        .order_by(desc(posts_table.c.created_at))
        .limit(max_per_page)
        .offset(offset1)
    )
    return await database.fetch_all(query)


async def get_posts_count():
    query = select([func.count()]).select_from(posts_table)
    return await database.fetch_val(query)


async def update_post(post_id: int, post: post_schema.PostModel):
    query = (
        posts_table.update()
        .where(posts_table.c.id == post_id)
        .values(title=post.title, content=post.content)
    )
    return await database.execute(query)



routers/posts.py
from app.schemas.posts import PostDetailsModel, PostModel
from app.schemas.users import User
from app.utils import posts as post_utils
from app.utils.dependencies import get_current_user
from fastapi import APIRouter, Depends, HTTPException, status

router = APIRouter()


@router.post("/posts", response_model=PostDetailsModel, status_code=201)
async def create_post(post: PostModel, current_user: User = Depends(get_current_user)):
    post = await post_utils.create_post(post, current_user)
    return post


@router.get("/posts")
async def get_posts(page: int = 1):
    total_cout = await post_utils.get_posts_count()
    posts = await post_utils.get_posts(page)
    return {"total_count": total_cout, "results": posts}


@router.get("/posts/{post_id}", response_model=PostDetailsModel)
async def get_post(post_id: int):
    return await post_utils.get_post(post_id)


@router.put("/posts/{post_id}", response_model=PostDetailsModel)
async def update_post(
    post_id: int, post_data: PostModel, current_user=Depends(get_current_user)
):
    post = await post_utils.get_post(post_id)
    if post["user_id"] != current_user["id"]:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="You don't have access to modify this post",
        )

    await post_utils.update_post(post_id=post_id, post=post_data)
    return await post_utils.get_post(post_id)



Подключим новые роуты, добавив в main.py
from app.routers import posts
app.include_router(posts.router)

Тестирование


Тесты мы будем писать на pytest:
$ pip install pytest

Для тестирования эндпоинтов FastAPI предоставляет специальный инструмент TestClient.

Напишем тест для эндпоинта, который не требует подключения к базе данных:

from app.main import app
from fastapi.testclient import TestClient

client = TestClient(app)


def test_health_check():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"Hello": "World"}

Как видите, все достаточно просто. Необходимо инициализировать TestClient, и использовать его для тестирования HTTP запросов.

Для тестирования остальных эндпоинтов, необходимо создать тестовую БД. Отредактируем файл main.py, добавив в него конфигурацию тестовой базы:

from os import environ

import databases

DB_USER = environ.get("DB_USER", "user")
DB_PASSWORD = environ.get("DB_PASSWORD", "password")
DB_HOST = environ.get("DB_HOST", "localhost")

TESTING = environ.get("TESTING")

if TESTING:
    # Используем отдельную базу данных для тестов
    DB_NAME = "async-blogs-temp-for-test"
    TEST_SQLALCHEMY_DATABASE_URL = (
        f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}"
    )
    database = databases.Database(TEST_SQLALCHEMY_DATABASE_URL)
else:
    DB_NAME = "async-blogs"
    SQLALCHEMY_DATABASE_URL = (
        f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:5432/{DB_NAME}"
    )
    database = databases.Database(SQLALCHEMY_DATABASE_URL)

Мы по-прежнему используем БД «async-blogs» для нашего приложения. Но если задано значение переменной окружение TESTING, тогда использовуется БД «async-blogs-temp-for-test».

Чтобы база «async-blogs-temp-for-test» автоматически создавалась при запуске тестов и удалялась после их выполнения, создадим фикстуру в файле tests/conftest.py:

import os

import pytest

# Устанавливаем `os.environ`, чтобы использовать тестовую БД
os.environ['TESTING'] = 'True'

from alembic import command
from alembic.config import Config
from app.models import database
from sqlalchemy_utils import create_database, drop_database


@pytest.fixture(scope="module")
def temp_db():
    create_database(database.TEST_SQLALCHEMY_DATABASE_URL) # Создаем БД
    base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
    alembic_cfg = Config(os.path.join(base_dir, "alembic.ini")) # Загружаем конфигурацию alembic 
    command.upgrade(alembic_cfg, "head") # выполняем миграции

    try:
        yield database.TEST_SQLALCHEMY_DATABASE_URL
    finally:
        drop_database(database.TEST_SQLALCHEMY_DATABASE_URL) # удаляем БД

Для создания и удаления БД воспользуемся библиотекой sqlalchemy_utils .

Используя фикстуру temp_db в тестах, мы сможем протестировать все эндпоинты нашего приложения:

def test_sign_up(temp_db):
    request_data = {
        "email": "[email protected]",
        "name": "Darth Vader",
        "password": "rainbow"
    }
    with TestClient(app) as client:
        response = client.post("/sign-up", json=request_data)
    assert response.status_code == 200
    assert response.json()["id"] == 1
    assert response.json()["email"] == "[email protected]"
    assert response.json()["name"] == "Darth"
    assert response.json()["token"]["expires"] is not None
    assert response.json()["token"]["access_token"] is not None

tests/test_posts.py
import asyncio

from app.main import app
from app.schemas.users import UserCreate
from app.utils.users import create_user, create_user_token
from fastapi.testclient import TestClient


def test_create_post(temp_db):
    user = UserCreate(
        email="[email protected]",
        name="Darth",
        password="rainbow"
    )
    request_data = {
      "title": "42",
      "content": "Don't panic!"
    }
    with TestClient(app) as client:
        # Create user and use his token to add new post
        loop = asyncio.get_event_loop()
        user_db = loop.run_until_complete(create_user(user))
        response = client.post(
            "/posts",
            json=request_data,
            headers={"Authorization": f"Bearer {user_db['token']['token']}"}
        )
    assert response.status_code == 201
    assert response.json()["id"] == 1
    assert response.json()["title"] == "42"
    assert response.json()["content"] == "Don't panic!"


def test_create_post_forbidden_without_token(temp_db):
    request_data = {
      "title": "42",
      "content": "Don't panic!"
    }
    with TestClient(app) as client:
        response = client.post("/posts", json=request_data)
    assert response.status_code == 401


def test_posts_list(temp_db):
    with TestClient(app) as client:
        response = client.get("/posts")
    assert response.status_code == 200
    assert response.json()["total_count"] == 1
    assert response.json()["results"][0]["id"] == 1
    assert response.json()["results"][0]["title"] == "42"
    assert response.json()["results"][0]["content"] == "Don't panic!"


def test_post_detail(temp_db):
    post_id = 1
    with TestClient(app) as client:
        response = client.get(f"/posts/{post_id}")
    assert response.status_code == 200
    assert response.json()["id"] == 1
    assert response.json()["title"] == "42"
    assert response.json()["content"] == "Don't panic!"


def test_update_post(temp_db):
    post_id = 1
    request_data = {
      "title": "42",
      "content": "Life? Don't talk to me about life."
    }
    with TestClient(app) as client:
        # Create user token to add new post
        loop = asyncio.get_event_loop()
        token = loop.run_until_complete(create_user_token(user_id=1))
        response = client.put(
            f"/posts/{post_id}",
            json=request_data,
            headers={"Authorization": f"Bearer {token['token']}"}
        )
    assert response.status_code == 200
    assert response.json()["id"] == 1
    assert response.json()["title"] == "42"
    assert response.json()["content"] == "Life? Don't talk to me about life."


def test_update_post_forbidden_without_token(temp_db):
    post_id = 1
    request_data = {
      "title": "42",
      "content": "Life? Don't talk to me about life."
    }
    with TestClient(app) as client:
        response = client.put(f"/posts/{post_id}", json=request_data)
    assert response.status_code == 401


tests/test_users.py
import asyncio
import pytest

from app.main import app
from app.schemas.users import UserCreate
from app.utils.users import create_user, create_user_token
from fastapi.testclient import TestClient


def test_sign_up(temp_db):
    request_data = {
        "email": "[email protected]",
        "name": "Darth",
        "password": "rainbow"
    }
    with TestClient(app) as client:
        response = client.post("/sign-up", json=request_data)
    assert response.status_code == 200
    assert response.json()["id"] == 1
    assert response.json()["email"] == "[email protected]"
    assert response.json()["name"] == "Darth"
    assert response.json()["token"]["expires"] is not None
    assert response.json()["token"]["token"] is not None


def test_login(temp_db):
    request_data = {"username": "[email protected]", "password": "rainbow"}
    with TestClient(app) as client:
        response = client.post("/auth", data=request_data)
    assert response.status_code == 200
    assert response.json()["token_type"] == "bearer"
    assert response.json()["expires"] is not None
    assert response.json()["access_token"] is not None


def test_login_with_invalid_password(temp_db):
    request_data = {"username": "[email protected]", "password": "unicorn"}
    with TestClient(app) as client:
        response = client.post("/auth", data=request_data)
    assert response.status_code == 400
    assert response.json()["detail"] == "Incorrect email or password"


def test_user_detail(temp_db):
    with TestClient(app) as client:
        # Create user token to see user info
        loop = asyncio.get_event_loop()
        token = loop.run_until_complete(create_user_token(user_id=1))
        response = client.get(
            "/users/me",
            headers={"Authorization": f"Bearer {token['token']}"}
        )
    assert response.status_code == 200
    assert response.json()["id"] == 1
    assert response.json()["email"] == "[email protected]"
    assert response.json()["name"] == "Darth"


def test_user_detail_forbidden_without_token(temp_db):
    with TestClient(app) as client:
        response = client.get("/users/me")
    assert response.status_code == 401


@pytest.mark.freeze_time("2015-10-21")
def test_user_detail_forbidden_with_expired_token(temp_db, freezer):
    user = UserCreate(
        email="[email protected]",
        name="Palpatine",
        password="unicorn"
    )
    with TestClient(app) as client:
        # Create user and use expired token
        loop = asyncio.get_event_loop()
        user_db = loop.run_until_complete(create_user(user))
        freezer.move_to("'2015-11-10'")
        response = client.get(
            "/users/me",
            headers={"Authorization": f"Bearer {user_db['token']['token']}"}
        )
    assert response.status_code == 401


P.S. Исходники


Вот собственно и все, репозиторий с исходниками из поста можно посмотреть на GitHub.

20 самых лучших сайтов для изучения Python

Python это элегантный, высокоуровневый язык программирования, относительно простой в изучении. К тому же, он отличается кроссплатформенностью, — пишет сайт pythonist.ru.

Последнее качество особенно важно, потому что вообще для работы с разными платформами разработчику приходится изучать разные языки программирования. На мобильных устройствах, к примеру, Android использует Java, а iOS — Swift или Objective-C. Для облегчения переноса программного обеспечения с одной платформы на другую есть специальные инструменты, но их применение имеет свои отрицательные стороны. Нативное приложение всегда лучше, чем портированное.

Python — один из самых рекомендуемых языков программирования в образовательной и исследовательской сферах. Это связано с легкостью его освоения. Чтобы проиллюстрировать, насколько Python легок в изучении, скажем, что его основы можно освоить за первый час работы. Множество студентов начинают свой путь в программировании с изучения именно этого языка.

В рейтинге популярности языков программирования TIOBE по состоянию на июнь 2020 года Python уверенно занимает третье место, хотя пять лет назад был на 8-й позиции. Это отлично демонстрирует, как быстро растет популярность языка.

Такому росту в немалой степени способствует изобилие обучающих ресурсов: руководств, курсов и книг по Python. Самые лучшие руководства позволят вам параллельно с изучением теории создать собственное маленькое приложение. Конечно, оно не будет особо выдающимся, но все равно это практика и отличный старт.

С чего начать?

Python считается одним из самых простых в изучении языков программирования, к тому же он чрезвычайно универсален. Вы можете использовать этот язык для чего угодно, от веб-разработки до разработки игр. Кроме того, изучив Python, вы в будущем с легкостью изучите и подобные ему языки, например, PHP или Ruby.

Лучший способ изучить что-либо — работать с предметом изучения. Языков программирования это касается в первую очередь. Следовательно, лучший способ начать изучение Python — выбрать урок или обучающий курс и погрузиться в него с головой.

Что касается изучения основ кодинга на Python, вы вполне можете справиться с этим самостоятельно. Нет никакой необходимости тратить тысячи долларов на получение специального образования или прохождение курсов программирования. А нужные навыки вы приобретете на практике, путем проб и ошибок.

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

Топ-20 сайтов для изучения Python

Прежде чем перейти непосредственно к описанию ресурсов, отметим, что сайты из первой десятки нашего списка считаются самыми лучшими ресурсами для изучения Python. Остальные указаны без учета какого-либо рейтинга. Абсолютное большинство ресурсов в нашем списке бесплатны (если ресурс платный, мы оговорим это отдельно).

1. Code Academy

Code Academy это бесплатный учебный ресурс для изучения программирования. На этой платформе вы найдете уроки по самым разным языкам, не только по Python.

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

Code Academy лучше всего подходит для начинающих и программистов среднего уровня. Здесь вы изучите общий синтаксис языка, научитесь работать со строками и условиями, познакомитесь с циклами, функциями, списками и словарями.

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

2. TutorialsPoint

Сайт TutorialsPoint напоминает Code Academy. Он тоже предлагает бесплатные уроки и возможность писать код прямо в окне браузера.

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

Мы назвали руководства TutorialsPoint самыми полными, потому что они покрывают и довольно сложные темы, такие как доступ к базам данных, CGI, программирование игр, использование многопоточности, обработку XML, сети, дизайн графических пользовательских интерфейсов и т. п.

3. Codementor.io

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

Каждый пост на этом сайте — отдельное руководство по какой-либо теме, например, об интеграции Node.js с Python, использовании декораторов и т. п.

4. PythonChallenge

Если вы не ищете легких путей и предпочитаете учиться, преодолевая трудности, PythonChallenge вам понравится.

Это не самый красивый сайт всех времен и народов, его дизайн определенно оставляет желать лучшего. Но там вы найдете отличные задачи и уроки, которые помогут вам в изучении Python.

5. Python Class от Google

Руководство по Python от Google по своей сути — электронный учебник. Материал в нем предназначен для опытных программистов, начиная от среднего уровня. Главы этого учебника хорошо написаны и доступным (английским) языком объясняют концепции, имеющие отношение к Python. Здесь вы получите чисто теоретические знания, без глубокого разбора отдельных тем или пошаговых руководств по созданию приложений.

В общем, это отличный вспомогательный материал для Python-разработчиков.

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

6. Python.org

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

Логично, что здесь есть и отличное руководство для начинающих, которое проведет вас по основам языка. Затем вы сможете обратиться к более сложным темам и познакомиться с различными библиотеками и модулями Python.

7. Электронная книга «Learn Python the Hard Way»

Еще один ресурс для тех, кто не боится сложностей. Бесплатную книгу «Learn Python the Hard Way» можно читать онлайн на любых устройствах, в т.ч. и мобильных. Также можно купить бумажную или электронную версию книги.

В настоящее время эту книгу ежегодно читают больше 1,5 млн. людей. Это впечатляющее число, особенно если представить, что все эти люди так или иначе работают с Python.

8. LearnPython.org

Мы уже говорили, что лучший способ изучить язык программирования — это работать с ним. Платформа LearnPython.org как раз и предоставляет возможность поработать с Python. Здесь вы найдете интерактивные руководства, а практиковаться в написании кода сможете прямо в браузере.

Новички начинают с достославного «Hello World», а затем постепенно продвигаются к более сложным темам (если, конечно, не забрасывают курс). Этот портал лучше всего подходит для программистов, еще не достигших среднего уровня.

9. Электронные книги «Invent with Python»

Еще одни проверенный способ хорошо усвоить учебный материал — наслаждаться процессом его изучения. Именно эта идея лежит в основе серии книг «Invent with Python» (прибл. «Создавай с Python»).

Каждое руководство, совет и урок в этой серии освещают подход к решению какой-то определенной задачи, и этот подход предполагает использование Python.

Например, книга «Invent Your Own Computer Games with Python» («Создавай собственные компьютерные игры при помощи Python») научит вас создавать игры. С каждым новым уроком игры будут становиться все более сложными, их создание будет требовать все более продвинутого использования языка. К концу книги вы начнете разбираться в этой теме настолько, что сможете самостоятельно создавать приложения или игры.

Онлайн-версии книг доступны бесплатно, но можно купить собственный экземпляр.

10. Dive into Python 3

«Dive into Python 3» это онлайн-книга, в которой объясняются отличия третьей версии языка Python от второй. Книга выпущена под лицензией Creative Commons, так что ее можно скачать бесплатно (в HTML или PDF-версии).

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

11. Pythonspot

Pythonspot это каталог ресурсов и материалов, касающихся Python. Весь контент разделен на категории: по уровню навыков, тематике (пользовательские интерфейсы, сети и т. д.) и платформе (Android, iOS и т.п.).

12. Онлайн-книга «Укус питона»

Книга «A Byte of Python» (автор — Swaroop Chitlur) это отличный учебник для начинающих. Более опытные программисты могут смело использовать его в качестве справочника — на случай, если нужно будет что-то вспомнить. Книга распространяется бесплатно, есть русский перевод.

13. Курс по Python на Coursera (от университета Райса)

Coursera, как и Code Academy, предлагает бесплатные онлайн-курсы для всех желающих. Но на Coursera большая часть курсов — от действующих колледжей и университетов.

Курс по Python создан университетом Райса. Его прохождение займет у вас несколько недель, так что нужно заранее быть готовым к этому и выделить время. Также потребуется регистрация — как если бы вы записывались на очный курс в университете. Хорошая новость состоит в том, что регистрация и сам курс совершенно бесплатны.

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

14. Ускоренный курс по Python

Создатели курса Crash into Python исходили из того, что вы уже опытный разработчик и разбираетесь в объектно-ориентированном программировании.

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

15. Real Python

Real Python это премиальный онлайн-курс с разными вариантами подписки. Оплатив подписку, вы получите доступ к больше чем 1300 страницам контента, 9 часам видео, к упражнениям и примерам кода. Впрочем, на сайте есть много отличных статей, которые можно читать совершенно бесплатно.

Цена: стартует от 20 долларов в месяц.

Real Python

16. Full Stack Python

Это портал для опытных разработчиков (начиная со среднего уровня). Если вы уже хорошо знаете Python, но хотели бы получить совет, куда двигаться дальше, посетите Full Stack Python. Там вам будут предложены варианты проектов: например, создание веб-приложения определенного вида, демо-версии сайта или модуля.

17. Python for Everybody

Если вы уже знакомы с программированием в целом, вас может заинтересовать портал Python for Everybody. Материалы на этом сайте по сути представляют собой онлайн-учебник по Python. Текстовую версию этого учебника можно скачать бесплатно.

18. Изучение основ Python в ходе создания виртуального домашнего питомца

Помните, как в 90-х все сходили с ума по тамагочи? Если нет, скажем вкратце, что это были милые виртуальные питомцы, о которых дети и взрослые могли заботиться. Может, звучит не сильно увлекательно, но это было правда интересно.

Пройдя этот курс по основам Python, вы получите базовые знания языка, а еще создадите собственную Python-версию тамагочи — PyPet.

19. CheckiO

В наше время для превращения скучных задач в увлекательные массово используется геймификация.

И хотя изучение программирования сложно назвать скучной задачей, геймификация позволяет сделать ее еще интереснее. С CheckiO вы сможете в увлекательной форме изучить Python и TypeScript. Это особенно полезно для тех, кому сложно поддерживать концентрацию на чтении или просмотре видео.

20. Элементы стиля Python

«The Elements of Python Style» это руководство по стилю написания кода на Python. Подобные гайды помогают поддерживать стандарт кода, которому смогут следовать все разработчики. Этот ресурс пригодится всем Python-программистам, но больше всего — более опытным.

Размещайте, выполняйте и кодируйте Python в облаке: PythonAnywhere

Python — отличный язык для обучения, но чтобы его освоить установлен и настроен на всех компьютерах ваших учеников. быть менее чем легким. PythonAnywhere предоставляет среду готово к работе, включая подсветку синтаксиса, редактор проверки ошибок, консоли Python 2 и 3, а также полный набор батарей в комплекте. Избегайте всех хлопот по установке Python на каждый ноутбук, и убедиться, что каждый может установить все нужные пакеты.

Распределять задания и отслеживать прогресс очень просто

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

Мы даже можем создать для вас массовые учетные записи студентов, и предварительно заполните их файлами, которые вы предоставляете — просто дайте нам знать!

У всех ваших учеников одинаковая среда

Та же операционная система, та же консоль, тот же текстовый редактор — сохраните себя от необходимости настраивать свои уроки и инструкции для Windows / Mac / Linux, а также от необходимости отлаживать проблемы в разных оболочках и редакторы.

… и они могут работать вместе

Ваши учащиеся также могут поделиться своими консолями друг с другом. — чтобы они могли работать над групповыми проектами удаленно или помогать друг другу в классе.

Уважаемый Python Anywhere @pythonanywhere, Спасибо, Вы даете возможность таким людям, как я, развивать жизненные навыки, которые я могу использовать где угодно!

— Нил Бергер (@ neiljacob23) 27 июля 2017 г.

@pythonanywhere не может быть проще в настройке и использовании.Мы очень рады протестировать наше приложение для учеников с учителями, когда начнется школа!

— Ники (@ nanselm2) 31 августа 2016 г.

Anaconda от @ContinuumIO + @pythonanywhere + @github = отличный способ изучить веб-разработку с Flask. Сделайте своего учителя онлайн-наставником. Выродок!

— Кирби Урнер (@ 4DsolutionsPDX) 31 июля 2016 г.

К лучшему, @pythonanywhere сделал сегодня БЕЗУПРЕЧНО легким объединение с учеником. Так здорово. По-прежнему остается лучшим ресурсом по Python.

— Раймонд Берг (@raymondberg) 19 мая 2016 г.

@pythonanywhere отличная функция учителя! Обожаю: D

— Арджун Шарма (@ arjoonn1) 1 марта 2016 г.

Рекомендуется @pythonanywhere для нового Parseltongue. Не ошибся! Он столкнулся с проблемой, и мы исправили ее за считанные минуты благодаря совместному использованию консоли.

— Раймонд Берг (@raymondberg) 9 января 2016 г.

Провел 1-часовой семинар по Python для людей, работающих с Windows-машинами, и все благодаря @pythonanywhere! #somuchwin

— Filipe Ximenes (@xima) 3 октября 2015 г.

Зарегистрируйтесь и попробуйте! »

Справочные страницы PythonAnywhere по обучению »

Начать работу на работе или в школе и продолжать дома

Поскольку PythonAnywhere работает в Интернете, он может следить за вами на любом компьютере. (или iPad, или Chromebook) с браузером, чтобы вы или ваши ученики могли работать откуда угодно.

Сколько это стоит?

Это бесплатно! Наши базовые учетные записи бесплатны, и мы взимаем плату только за более продвинутые услуги (например, профессиональный хостинг веб-приложений или требования), ни один из которых не требуется для базового типа «введение в программирование» курсы. Если вам нужно больше вычислительной мощности, тогда связаться — вы также можете получить представление о наших ценах на странице цен.

Ограничения

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

.Сайт

— Перехватчик конфигурации для конкретного сайта — документация Python 3.8.6

Исходный код: Lib / site.py


Этот модуль автоматически импортируется во время инициализации. Автомат импорт можно подавить, используя опцию интерпретатора -S .

Импорт этого модуля добавит пути, зависящие от сайта, к пути поиска модуля и добавьте несколько встроенных команд, если не использовалось -S . В таком случае этот модуль можно безопасно импортировать без автоматического изменения пути поиска модуля или дополнения к встроенным.Для явного запуска обычного, зависящего от сайта дополнений вызовите функцию site.main () .

Изменено в версии 3.3: Импорт модуля, используемого для запуска манипуляции с путями, даже при использовании -S .

Он начинается с создания до четырех каталогов из головной и хвостовой частей. Для головной части используется sys.prefix и sys.exec_prefix ; пустые головы пропускаются. Для хвостовой части используется пустая строка, а затем lib / site-packages (в Windows) или lib / python X.Y / site-packages (в Unix и Macintosh). Для каждого различных комбинаций голова-хвост, он видит, относится ли это к существующему каталог, и если да, то добавляет его в sys.path , а также проверяет новый добавлен путь для файлов конфигурации.

Изменено в версии 3.5: удалена поддержка каталога site-python.

Если файл с именем «pyvenv.cfg» существует на один каталог выше sys.executable, sys.prefix и sys.exec_prefix устанавливаются в этот каталог и также проверяется наличие пакетов сайтов (sys.base_prefix и sys.base_exec_prefix всегда будет «настоящими» префиксами Python установка). Если «pyvenv.cfg» (файл конфигурации начальной загрузки) содержит ключ «include-system-site-packages» установлен на любое значение, кроме «true» (без учета регистра) префиксы системного уровня не будут искал сайты-пакеты; в противном случае они будут.

Файл конфигурации пути — это файл, имя которого имеет вид имя .pth и существует в одном из четырех упомянутых выше каталогов; его содержание дополнительные элементы (по одному в строке) для добавления в sys.путь . Несуществующие предметы никогда не добавляются к sys.path , и не проверяется, ссылается ли элемент на каталог, а не файл. В sys.path больше, чем один раз. Пустые строки и строки, начинающиеся с # , пропускаются. Линии начинаются с import (с последующим пробелом или табуляцией) выполняются.

Примечание

Исполняемая строка в файле .pth запускается при каждом запуске Python, независимо от того, будет ли фактически использоваться конкретный модуль.Таким образом, его воздействие следует свести к минимуму. Основное предназначение исполняемых строк — сделать соответствующий модуль (ы) импортируемый (загрузить сторонние обработчики импорта, настроить PATH и т. д.). Любая другая инициализация должна выполняться после того, как модуль фактический импорт, если и когда это произойдет. Ограничение фрагмента кода одной строкой — это намеренная мера чтобы не допустить добавления сюда чего-либо более сложного.

Например, предположим, что sys.prefix и sys.exec_prefix установлены на / usr / local .Затем библиотека Python X.Y устанавливается в / usr / local / lib / python X.Y . Предположим, что это подкаталог / usr / local / lib / python X.Y / site-packages с тремя поддиректории, foo , bar и spam и два пути файлы конфигурации, foo.pth и bar.pth . Предполагать foo.pth содержит следующее:

 # конфигурация пакета foo

фу
бар
пухлый
 

и бар.pth содержит:

 # конфигурация пакета bar

бар
 

Затем следующие каталоги для конкретных версий добавляются в sys.path , в следующем порядке:

 /usr/local/lib/pythonX.Y/site-packages/bar
/usr/local/lib/pythonX.Y/site-packages/foo
 

Обратите внимание, что bletch опущено, потому что его не существует; бар каталог предшествует каталогу foo , потому что приходит bar.pth по алфавиту до foo.pth ; и спам опускается, потому что он не упоминается ни в одном из файлов конфигурации пути.

После этих манипуляций с путями делается попытка импортировать модуль с именем sitecustomize , который может выполнять произвольные настройки для конкретного сайта. Обычно создается системным администратором в пакетах сайтов. каталог. Если этот импорт завершился неудачно с ImportError или его подклассом исключение, а атрибут name исключения равен sitecustomize , это молча игнорируется.Если Python запущен без доступных потоков вывода, как с pythonw.exe в Windows (который по умолчанию используется для запуска IDLE), попытка вывода из sitecustomize игнорируется. Любое другое исключение вызывает тихий и, возможно, загадочный сбой процесса.

После этого делается попытка импортировать модуль с именем usercustomize , который может выполнять произвольные пользовательские настройки, если ENABLE_USER_SITE истинно. Этот файл предназначен для создания в каталог user site-packages (см. ниже), который является частью sys.путь , если отключен -s . Если этот импорт завершится неудачно с ImportError или исключение его подкласса, а атрибут name исключения равен 'usercustomize' , он игнорируется.

Обратите внимание, что для некоторых систем, отличных от Unix, sys.prefix и sys.exec_prefix являются пусто, и манипуляции с путями пропускаются; однако импорт sitecustomize и usercustomize все еще предпринимаются.

Конфигурация Readline

В системах, поддерживающих readline , этот модуль также импортирует и настроить модуль rlcompleter , если Python запускается в интерактивный режим и без опции -S . По умолчанию включен tab-comp

.

28,14. site — Хук настройки для конкретного сайта — документация Python 2.7.18

Исходный код: Lib / site.py


Этот модуль автоматически импортируется во время инициализации. Автомат импорт можно подавить, используя опцию интерпретатора -S .

Импорт этого модуля добавит пути, зависящие от сайта, к пути поиска модуля и добавьте несколько встроенных функций.

Он начинается с создания до четырех каталогов из головной и хвостовой частей.Для головной части используется sys.prefix и sys.exec_prefix ; пустые головы пропускаются. Для хвостовой части используется пустая строка, а затем lib / site-packages (в Windows) или lib / python X.Y / site-packages , а затем lib / site-python (на Unix и Macintosh). Для каждой отдельной комбинации головы и хвоста он видит если он относится к существующему каталогу, и если да, добавляет его в sys.path и также проверяет недавно добавленный путь для файлов конфигурации.

Файл конфигурации пути — это файл, имя которого имеет вид имя .pth и существует в одном из четырех упомянутых выше каталогов; его содержание дополнительные элементы (по одному в строке), которые нужно добавить в sys.path . Несуществующие предметы никогда не добавляются к sys.path , и не проверяется, ссылается ли элемент на каталог, а не файл. В sys.path больше, чем один раз. Пустые строки и строки, начинающиеся с # , пропускаются.Линии начинаются с import (с последующим пробелом или табуляцией) выполняются.

Изменено в версии 2.6: теперь после ключевого слова import требуется пробел или табуляция.

Например, предположим, что sys.prefix и sys.exec_prefix установлены на / usr / local . Затем библиотека Python X.Y устанавливается в / usr / local / lib / python X.Y . Предположим, что это подкаталог / usr / local / lib / python X.Y / site-packages с тремя поддиректории, foo , bar и spam и два пути файлы конфигурации, foo.pth и бар. pth . Предполагать foo.pth содержит следующее:

 # конфигурация пакета foo

фу
бар
пухлый
 

и бар.pth содержит:

 # конфигурация пакета bar

бар
 

Затем следующие каталоги для конкретных версий добавляются в sys.path , в следующем порядке:

 /usr/local/lib/pythonX.Y/site-packages/bar
/usr/local/lib/pythonX.Y/site-packages/foo
 

Обратите внимание, что bletch опущено, потому что его не существует; бар каталог предшествует foo каталог, потому что bar.pth приходит в алфавитном порядке перед foo.pth ; и спам опускается, потому что он не упоминается ни в одном из файлов конфигурации пути.

После этих манипуляций с путями делается попытка импортировать модуль с именем sitecustomize , который может выполнять произвольные настройки для конкретного сайта. Обычно создается системным администратором в пакетах сайтов. каталог. Если этот импорт завершается неудачно с исключением ImportError , это молча игнорируется.Если Python запущен без доступных потоков вывода, как с pythonw.exe в Windows (который по умолчанию используется для запуска IDLE), попытка вывода из sitecustomize игнорируется. Любое исключение другое чем ImportError вызывает тихий и, возможно, таинственный отказ процесс.

После этого делается попытка импортировать модуль с именем usercustomize , который может выполнять произвольные пользовательские настройки, если ENABLE_USER_SITE истинно.Этот файл предназначен для создания в каталог user site-packages (см. ниже), который является частью sys.path , если только отключен -s . Ошибка ImportError будет игнорироваться.

Обратите внимание, что для некоторых систем, отличных от Unix, sys.prefix и sys.exec_prefix являются пусто, и манипуляции с путями пропускаются; однако импорт sitecustomize и usercustomize все еще предпринимаются.

сайт. ПРЕФИКСЫ

Список префиксов для каталогов сайтов-пакетов.

сайт. ENABLE_USER_SITE

Флаг, показывающий состояние каталога сайтов-пакетов пользователя. Истинно означает что он включен и был добавлен в sys.path . Ложь означает, что это был отключен по запросу пользователя (с -s или PYTHONNOUSERSITE ). Нет означает, что он был отключен в целях безопасности причины (несоответствие между идентификатором пользователя или группы и эффективным идентификатором) или администратор.

сайт. САЙТ_ПОЛЬЗОВАТЕЛЯ

Путь к пользовательским сайтам-пакетам для запущенного Python. Может быть Нет , если getusersitepackages () еще не вызывали. Значение по умолчанию ~ / .local / lib / python X.Y / site-packages для UNIX и Mac без фреймворка Сборки OS X, ~ / Library / Python / X.Y / lib / python / site-packages для Mac сборки фреймворка и % APPDATA% \ Python \ Python XY \ site-packages в Windows.Этот каталог является каталогом сайта, что означает, что .pth файлы в нем будут обрабатываться.

сайт. БАЗА_ПОЛЬЗОВАТЕЛЯ

Путь к базовому каталогу для пользовательских сайтов-пакетов. Может быть Нет

.

HOWTO Использование Python в Интернете — документация по Python 2.7.18

Программирование для Интернета стало горячей темой с момента появления «Web 2.0», который фокусируется на пользовательском контенте на веб-сайтах. Всегда было Можно было использовать Python для создания веб-сайтов, но это была довольно утомительная задача. Поэтому было создано множество фреймворков и вспомогательных инструментов, чтобы помочь разработчикам в создании более быстрых и надежных сайтов. Этот HOWTO описывает некоторые методы, используемые для объединения Python с веб-сервером для создания динамический контент.Это не является полным введением, так как эта тема слишком широки, чтобы их можно было охватить в одном документе. Однако краткий обзор из самых популярных библиотек.

См. Также

Хотя этот HOWTO пытается дать обзор Python в сети, он не может всегда будьте настолько актуальны, насколько хотите. Веб-разработка на Python быстро движется вперед, поэтому вики-страница по веб-программированию может быть более синхронизирована с Недавнее развитие.

Низкоуровневое представление

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

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

Большинство HTTP-серверов написаны на C или C ++, поэтому они не могут выполнять код Python. напрямую — нужен мост между сервером и программой. Эти мосты, или, скорее, интерфейсы, определяют, как программы взаимодействуют с сервером. Было много попыток создать наилучший интерфейс, но стоит упомянуть лишь некоторые из них.

Не каждый веб-сервер поддерживает каждый интерфейс. Многие веб-серверы поддерживают только старые, устаревшие интерфейсы; однако их часто можно расширить с помощью сторонние модули для поддержки более новых.

Общий интерфейс шлюза

Этот интерфейс, обычно называемый «CGI», является самым старым и поддерживается практически каждым веб-сервером из коробки. Программы, использующие CGI для связь со своим веб-сервером должна запускаться сервером для каждого запрос. Итак, каждый запрос запускает новый интерпретатор Python, что требует некоторого время для запуска — таким образом, весь интерфейс можно использовать только при низкой нагрузке ситуации.

Преимущество CGI в том, что он прост — написание программы Python, использующей CGI — это примерно три строки кода. Эта простота цена: он мало что помогает разработчику.

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

См. Также

Стандартная библиотека Python включает несколько модулей, которые полезны для создание простых программ CGI:

  • cgi — Обработка пользовательского ввода в сценариях CGI

  • cgitb — Отображает красивые трассировки при возникновении ошибок в CGI приложений, вместо отображения сообщения «500 Internal Server Error»

Вики Python содержит страницу сценариев CGI с некоторой дополнительной информацией о CGI в Python.

Простой скрипт для тестирования CGI

Чтобы проверить, работает ли ваш веб-сервер с CGI, вы можете использовать этот короткий и простая программа CGI:

 #! / Usr / bin / env python
# - * - кодировка: UTF-8 - * -

# включить отладку
импорт cgitb
cgitb.enable ()

print "Content-Type: text / plain; charset = utf-8"
Распечатать

печать "Hello World!"
 

В зависимости от конфигурации вашего веб-сервера вам может потребоваться сохранить этот код с помощью расширение .py или .cgi . Кроме того, этот файл может также потребоваться в папке cgi-bin из соображений безопасности.

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

Настройка CGI на собственном сервере

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

Если вы являетесь собственным администратором или хотите настроить CGI для тестирования на ваши собственные компьютеры, вы должны настроить его самостоятельно. Нет ни одного способ настройки CGI, так как существует множество веб-серверов с разными варианты конфигурации.В настоящее время наиболее широко используемым бесплатным веб-сервером является Apache HTTPd, сокращенно Apache. Apache может быть легко устанавливается почти в каждой системе с помощью системы управления пакетами орудие труда. lighttpd — еще одна альтернатива, сказал, что имеет лучшую производительность. Во многих системах этот сервер также может быть устанавливается с помощью инструмента управления пакетами, поэтому вручную компилирует Интернет сервер может не понадобиться.

  • На Apache вы можете взглянуть на руководство по динамическому контенту с CGI, где все описан.В большинстве случаев достаточно просто установить + ExecCGI . В в руководстве также описаны наиболее распространенные ошибки, которые могут возникнуть.

  • На lighttpd нужно использовать модуль CGI, который можно настроить простым способом. Это сводится к правильной настройке cgi.assign .

Общие проблемы со сценариями CGI

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

Вот некоторые из этих потенциальных проблем:

  • Скрипт Python не помечен как исполняемый. Когда скрипты CGI не исполняемый файл большинства веб-серверов позволит пользователю загрузить его вместо запускает его и отправляет результат пользователю. Для запуска сценариев CGI правильно в Unix-подобных операционных системах необходимо установить бит + x . Использование chmod a + x your_script.py может решить эту проблему.

  • В Unix-подобной системе окончание строки в файле программы должно быть Unix стиль окончания строк.Это важно, потому что веб-сервер проверяет первая строка скрипта (называемая shebang) и пытается запустить программу указано там. Его легко путают окончания строк Windows (Carriage Возврат и перевод строки, также называемый CRLF), поэтому вам нужно преобразовать файл в Окончания строк Unix (только Line Feed, LF). Это можно сделать автоматически загрузка файла по FTP в текстовом режиме вместо двоичного, но предпочтительный способ — просто сказать вашему редактору сохранить файлы с помощью строки Unix концовки.Большинство редакторов поддерживают это.

  • Ваш веб-сервер должен иметь возможность читать файл, и вы должны убедиться, что разрешения верны. В unix-подобных системах сервер часто работает как пользователь. и сгруппируйте www-data , поэтому, возможно, стоит попробовать изменить файл владение, или сделать мир файла доступным для чтения с помощью chmod a + r ваш_script.py .

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

  • В Unix-подобных системах путь к интерпретатору в shebang ( #! / Usr / bin / env python ) должно быть правильным. Эта линия вызывает / usr / bin / env , чтобы найти Python, но он не удастся, если нет / usr / bin / env , или если Python отсутствует на пути веб-сервера. Если ты знаешь там, где установлен ваш Python, вы также можете использовать этот полный путь. В команды , где python и type -p python могут помочь вам найти где он установлен.Как только вы узнаете путь, вы можете изменить шебанг соответственно: #! / usr / bin / python

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *