Comments 44
Хороший был цикл статей, радует, что автор решил актуальную версию написать. А вам спасибо за перевод.
Что бы написать по русски «Привет, Мир!» потребуется скорректировать
модуль routes.py
Добавить строку # -*- coding: utf-8 -*-

А разве это необходимо? Ведь в третьем питоне строки по умолчанию в юникоде.

Since Python 3.0, the language features a str type that contain Unicode characters, meaning any string created using «unicode rocks!», 'unicode rocks!', or the triple-quoted string syntax is stored as Unicode.

The default encoding for Python source code is UTF-8, so you can simply include a Unicode character in a string literal:


P.S. За перевод спасибо.
У Девида Бизли на 56 странице… Язык Python позволяет записывать программный код в другой кодировке,
для чего в первой или во второй строке программы необходимо добавить
специальный комментарий, указывающий тип кодировки:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
Мы не про другую кодировку говорим.
А конкретно про utf-8.
В Python > 3 весь текст по умолчанию в utf-8, и обрабатываться он будет как utf-8.
Исключение если мы получаем текст из внешнего источника в другой кодировке.
В том коде что у вас в статье, русские символы обработаются корректно. Если вы не храните исходный код в Windows-1251 например.
Вообщем, как я понимаю, суть в том, что в python 3 utf-8 по умолчанию для типов строк. Во 2-м было два типа: Строковые и юникодные. Для юникодных надо было ставить символ u перед первой кавычкой или encode('utf-8') в конце. Но это не распространяется на кодировку файла. Она может быть любой. Поэтому требуется ее определить при наличии национальных символов в тексте. Ваша фраза >>> В Python > 3 весь текст по умолчанию в utf-8, и обрабатываться он будет как utf-8.… относится к типу строковых переменных, но не к кодировке файлов.

Там же у Бизли. Исходные тексты программ на языке Python обычно записываются в стандартной 7-битовой кодировке ASCII. Однако пользователи, работающие
в среде с поддержкой Юникода, могут посчитать это ограничение неудоб-
ным, особенно когда возникает необходимость в создании большого коли-
чества строковых литералов с национальными символами.


Если разобрать, что происходит при запуске программы на python, то мы попадем в модуле site.py в функцию aliasmbcs, где видно, что в случае с виндой и кодировкой все не просто.

def aliasmbcs():
    """On Windows, some default encodings are not provided by Python,
    while they are always available as "mbcs" in each locale. Make
    them usable by aliasing to "mbcs" in such a case."""
    if sys.platform == 'win32':
        import locale, codecs
        enc = locale.getdefaultlocale()[1]
        if enc.startswith('cp'):            # "cp***" ?
            try:
                codecs.lookup(enc)
            except LookupError:
                import encodings
                encodings._cache[enc] = encodings._unknown
                encodings.aliases.aliases[enc] = 'mbcs'

Неправильно понимаете, в питоне 3 и строки по умолчанию юникодные, и кодировка файла по умолчанию utf-8 — всё сразу. Писать # -*- coding: utf-8 -*- бессмысленно


Откройте своего Бизли на странице 772, и увидите там:


В Python 3 предполагается, что исходные тексты программ набираются в кодировке UTF-8.
Хотя тут стоит упомянуть потенциальный выстрел в ногу: текстовые файлы открываются на чтение и запись в системной кодировке, которая вовсе не обязательно utf-8. Поэтому в open я всегда прописываю аргумент encoding='utf-8', чтоб на винде проблем не было (а для чтения вообще utf-8-sig, чтобы символ BOM нормально обрабатывался)
Сейчас посмотрел в доку Python 3 Source Code Encoding

Вот что там говорится:
By default, Python source files are treated as encoded in UTF-8. In that encoding, characters of most languages in the world can be used simultaneously in string literals, identifiers and comments — although the standard library only uses ASCII characters for identifiers, a convention that any portable code should follow. To display all these characters properly, your editor must recognize that the file is UTF-8, and it must use a font that supports all the characters in the file.


Но вот с Windows совсем другое дело, необходимо указывать кодировку, когда она отличная
от UTF-8.

Тогда надо сделать уточнение, что это касается Windows,
а так-же тех случаев когда исходники в отличной от UTF-8 кодировке.

Но вот с Windows совсем другое дело, необходимо указывать кодировку.

Я не понял, откуда такой вывод? Создал сейчас Python-файл в Блокноте без всяких явных указаний кодировок —


всё отлично работает как utf-8

Это потому что сам файл сохранен как UFT-8.

А теперь проверяем с указанием кодировки Windows-1251 (Linux, Python 3.6.1)

SyntaxError: Non-UTF-8 code starting with '\xcf' in file ./main.py on line 1, but no encoding declared;

А, я невнимательный, часть «когда она отличная от UTF-8» проглядел, тогда согласен, сорри
Развели дискуссию. По факту, от наличия строки описания кодировки нет минусов. Поэтому, ее наличие приносит исключительно пользу в виду универсальности. Но не является обязательным.

2018 год на дворе, почему сайты на питоне до сих пор не оформляют как полноценные самодостаточные пакеты? Пакет с именем app не загрузишь на PyPI. В данном случае, конечно, достаточно переименовать app во что-нибудь адекватное, но меня расстраивает, что это не делают изначально (джанги это тоже касается, кстати)

Простите, а зачем "сайты на питоне" оформлять как "самодостаточные пакеты" и загружать на PyPl?

Чтобы другие люди могли легко поднимать их у себя, ваш Капитан Очевидность. Да и деплой упрощается даже без PyPI — копируем whl-файл на сервер, pip install, migrate и в принципе всё

Это лишь ваше личное мнение. Ничего не мешает сайту быть пакетом. У меня есть два сайта на фласке, опубликованные на PyPI, можете поискать и попробовать запустить у себя если интересно
Вне всяких сомнений это мое мнение. Я размышлял над вашим вопросом и просто не нашел такой необходимости оформить сайт на PyPi.

Конечно спасибо, посмотрю. Конечно интересно!

Нужность загрузки на PyPI действительно спорная (помимо двух упомянутых сайтов у меня есть ещё несколько, которые я не гружу на PyPI, потому что зачем), но тем не менее не вижу смысла не оформлять сайт как пакет изначально, так как пакет удобнее в пользовании (деплой через pip install по-моему намного лучше, чем какой-то убогий git pull) и в будущем передумать будет сильно труднее, чем изначально сделать всё правильно

Мне кажется, что если возникает необходимость ЧАСТО разворачивать свой веб-сайт на разных серверах, то pip install git+ssh://git@gitlab.yourcompany.com/user/project@release-1.0.5 гораздо уместнее.
Опять же, для этого сайт должен быть оформлен как пакет (setup.py и всё такое)
Давайте еще все это завернем в .deb и .rpm, только зачем?
Ответ прост: «Потому, что можем!»
Действительно, зачем? deb и rpm привязаны к конкретным дистрибутивам и пользы от них мало, а whl ставится куда угодно
Если вы используете Microsoft Windows, используйте команду вместо экспорта в команде выше.

Саму команду set пропустили.

(только учусь, ногами не бейте)
virtualenv venv #Создал виртуальную среду
venv\Scripts\activate #Активировал, поигрался
venv\Scripts\deactivate #Деактивировал
Что делать с папкой venv, оставшейся? Её можно просто удалить?
Ну, если наигрался, то да! А если собираешься другие части книги делать, то надо оставить.
Для того что бы запустить сервер на локальной машине завтра или послезавтра тебе надо активировать виртуальное окружение и выполнить flask run. Без venv\Scripts\activate ничего не выйдет!
Пожалуй это самый крутой учебный материал по Flask и Python, который я только видел.

Но у меня несколько отвелечённый вопрос — может быть кто-нибудь знает что-то подобное для PHP и какого-нибудь его фреймворка? Что бы человеку, знающему синтаксис языка, можно было пройти весь путь от проектирования приложения до деплоя.
Вопрос, а при изменении содержимого скриптов, сервер сам переопределяет что содержимое скриптов изменилось или надо перезапускать сервер?
Надо перезапускать вручную, если значение FLASK_DEBUG=0. В режиме отладки он сам перезапускается. Смотри 7-ю главу
следует упомянуть про вторую важную функцию, которая включена в режиме отладки — перезагрузка. Это очень полезная функция разработки, которая автоматически перезапускает приложение при изменении исходного файла. Если вы выполните flask run в режиме отладки, можно продолжать работать в своем приложении и при каждом сохранении файла, приложение перезапустится

Что-то вот не перезапускается сервер, если изменять файл шаблона по пути ./app/templates/index.html. Ни export FLASK_DEBUG=1, ни если передать параметр flask run --reload, ни если в ./app/__init__.py прописать app.debug = True не помогают, а изменения в ./app/routes.py, например, отслеживает...

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

Запутался я тут в трех соснах. :(
Непонятно откуда в конце появляется файл microblog.py и каково его назначение?
Насколько я понял, приложение создается в __init__.py в строке app = Flask(__name__)
У меня получилось запустить сервер только после импорта set FLASK_APP=__init__.py, но фласк ничего не отдает.
Если накопипасть все в один файл из мануала на сайте фласка и запустить его напрямую
if __name__ == '__main__':
app.run(debug=True))
то работает.
Какая у вас структура каталогов?
Посмотрите как устроено здесь

Запускать так:
(venv) $ export FLASK_APP=microblog.py
(venv) $ flask run
Жмакаем Ctl+F. Вводим в поле поиска по странице microblog.py и гдето примерно так по середине этой главы находим:
Чтобы завершить приложение, вам нужно создать сценарий Python на верхнем уровне, определяющий экземпляр приложения Flask. Давайте назовем этот скрипт microblog.py и определим его как одну строку, которая импортирует экземпляр приложения:

from app import app


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

microblog/
venv/
app/
. __init__.py
. routes.py
microblog.py

Верьте или нет, но первая версия приложения завершена! Прежде чем запускать его, Flask нужно сообщить, как его импортировать, установив переменную среды FLASK_APP:

(venv) $ export FLASK_APP=microblog.py
Хочу выразить большую благодарность за труд!
Также, хочу отметить, что в файле app/__init__.py, в инструкции импорта, лучше вписать точку, вместо явного определения имени текущего каталога (пакета Python), это не будет вызывать взрыв мозга, что откуда берется и будет ясность. Также, если пакет переименуется, то ничего из этого не сломается. т.е, это:

from flask import Flask

app = Flask(__name__)

from app import routes


лучше заменить на это:

from flask import Flask

app = Flask(__name__)

from . import routes
Может быть! Это к автору… Он отвечает, когда ему пишешь. Возможно эта точка появится в какой то из следующих глав.
Также, хочу отметить, что в файле app/init.py, в инструкции импорта, лучше вписать точку, вместо явного определения имени текущего каталога (пакета Python), это не будет вызывать взрыв мозга, что откуда берется и будет ясность.

Меня учили ровно наоборот: при точке непонятно, откуда это дело импортируется, приходится идти путь к текущему файлу смотреть, отрываясь от кода.


Также, если пакет переименуется, то ничего из этого не сломается

Меня учили ровно наоборот: при переименовании или перемещении точка может замаскировать сломавшиеся импорты, поэтому лучше прописывать всё явно, чтобы на сложных случаях вылетел ImportError, а не непонятно что, когда случайно импортировался другой подмодуль с таким же именем. (Хотя, возможно, к __init__ это не относится, но ведь явное лучше неявного же?)


Не знаю, как часто это всё встречается на практике, но такое мнение тоже есть.

Меня учили ровно наоборот

Вполне может быть так лучше, как Вас учили.


но ведь явное лучше неявного же?

В том-то и дело, что в этих строчках нужно напрягаться и вспоминать, так как здесь не явно, что действительно Python умеет и может импортировать:


app = Flask(__name__)
from app import routes

На слух это так: из экземпляра app импортровать routes. Если бы пакет (текущий каталог) был бы назван, например как myapp, то у меня бы вопроса не возникло:


app = Flask(__name__)
from myapp import routes

А одна точка (.) — это явное указание, также как и в файловой системе, что импортировать нужно из текущего каталога где этот модуль расположен.

Если вы используете любую версию Python старше 3.4 (включая выпуск 2.7), виртуальные среды не поддерживаются изначально.

Должно быть младше же?

Python 2.7 старше (старее), чем Python 3.4


по другому: Python 3.4 моложе (новее), чем Python 2.7

Only those users with full accounts are able to leave comments. Log in, please.