воскресенье, 30 июня 2013 г.

Настройка приложения Flask в режиме FastCGI

Перевод статьи: FastCGI

FastCGI - это один из вариантов развёртывания приложения на серверах nginx, lighttpd и cherokee; за описанием других опций обратитесь к разделам uWSGI и Самостоятельные контейнеры WSGI. Для использования приложения WSGI с любым из этих серверов необходимо сначала настроить сервер FastCGI. Наиболее популярен flup, который будет использоваться в этом руководстве. Убедитесь в том, что установили его, прежде чем продолжить чтение.

Предварительная проверка

Удостоверьтесь, что вызовы app.run() в файле приложения находятся внутри блока if __name__ == '__main__': или вынесены в отдельный файл. Просто убедитесь в отсутствии подобных вызовов, потому что если вы решили воспользоваться FastCGI для запуска приложения, то запускать локальный сервер WSGI не нужно.

Создание файла .fcgi

Для начала нужно создать файл сервера FastCGI. Давайте назовём его yourapplication.fcgi:
#!/usr/bin/python
from flup.server.fcgi import WSGIServer
from yourapplication import app
if __name__ == '__main__':
    WSGIServer(app).run()
Этого достаточно для работы Apache, однако nginx и старые версии lighttpd требуют явного указания сокетов для связи с сервером FastCGI. Для этого нужно передать путь к сокет-файлу в WSGIServer:
WSGIServer(application, bindAddress='/path/to/fcgi.sock').run()
Этот путь должен быть точно таким же, какой был указан в настройках сервера.

Сохраните файл yourapplication.fcgi где-нибудь, где вы сможете потом найти его. Неплохо положить его в /var/www/yourapplication или в какое-то другое подходящее место.

Убедитесь, что у этого файла установлен флаг выполнения, чтобы сервер мог его выполнить:
# chmod +x /var/www/yourapplication/yourapplication.fcgi
Настройка Apache

Приведённый выше пример достаточно хорош для того, чтобы использовать его при развёртывании с Apache, однако файл .fcgi будет встречаться в URL приложения, например: example.com/yourapplication.fcgi/news/. Есть несколько способов настройки приложения для того, чтобы убрать yourapplication.fcgi из URL. Предпочтительный способ - это использование директивы ScriptAlias:
<VirtualHost *>
  ServerName example.com
  ScriptAlias / /path/to/yourapplication.fcgi/
</VirtualHost>
Если задать ScriptAlias нельзя, например на веб-узле, настроенном для нескольких пользователей, то можно воспользоваться промежуточным приложением WSGI для удаления yourapplication.fcgi из URL. Настройте .htaccess:
<IfModule mod_fcgid.c>
  AddHandler fcgid-script .fcgi
  <Files ~ (\.fcgi)>
    SetHandler fcgid-script
    Options +FollowSymLinks +ExecCGI
  </Files>
</IfModule>

<IfModule mod_rewrite.c>
  Options +FollowSymlinks
  RewriteEngine On
  RewriteBase /
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ yourapplication.fcgi/$1 [QSA,L]
</IfModule>
Теперь настроим yourapplication.fcgi:
#!/usr/bin/python
#: не обязательный путь к каталогу с локальными пакетами python
import sys

sys.path.insert(0, '<локальный_путь>/lib/python2.6/site-packages')

from flup.server.fcgi import WSGIServer
from yourapplication import app

class ScriptNameStripper(object):
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        environ['SCRIPT_NAME'] = ''
        return self.app(environ, start_response)

app = ScriptNameStripper(app)

if __name__ == '__main__':
    WSGIServer(app).run()
Настройка lighttpd

Базовая настройка FastCGI для lighttpd выглядит следующим образом:
fastcgi.server = ("/yourapplication.fcgi" =>
  ((
    "socket" => "/tmp/yourapplication-fcgi.sock",
    "bin-path" => "/var/www/yourapplication/yourapplication.fcgi",
    "check-local" => "disable",
    "max-procs" => 1
  ))
)

alias.url = (
  "/static/" => "/path/to/your/static"
)

url.rewrite-once = (
  "^(/static($|/.*))$" => "$1",
  "^(/.*)$" => "/yourapplication.fcgi$1"
Не забудьте включить модули FastCGI, alias и rewrite. Эта настройка закрепит приложение за /yourapplication. Если нужно, чтобы приложение работало в корне URL, понадобится обойти недоработку lighttpd при помощи промежуточного приложения LighttpdCGIRootFix.

Убедитесь, что применяете его лишь в том случае, если подключили приложение к корню URL. А также, обратитесь к документации Lighttpd за более подробной информацией о FastCGI и Python (отметим, что явная передача сокет-файла в run() больше не требуется).

Настройка nginx

Установка приложений FastCGI в nginx немного отличается, потому что по умолчанию программе не передаются параметры FastCGI.

Базовая конфигурация FastCGI nginx для flask выглядит следующим образом:
location = /yourapplication { rewrite ^ /yourapplication/ last; }
location /yourapplication { try_files $uri @yourapplication; }
location @yourapplication {
  include fastcgi_params;
  fastcgi_split_path_info ^(/yourapplication)(.*)$;
  fastcgi_param PATH_INFO $fastcgi_path_info;
  fastcgi_param SCRIPT_NAME $fastcgi_script_name;
  fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
}
Эта конфигурация привязывает приложение к /yourapplication. Привязать приложение к корню URL несколько проще, потому что не нужно думать о том, какие значения использовать в PATH_INFO и SCRIPT_NAME:
location / { try_files $uri @yourapplication; }
location @yourapplication {
  include fastcgi_params;
  fastcgi_param PATH_INFO $fastcgi_script_name;
  fastcgi_param SCRIPT_NAME "";
  fastcgi_pass unix:/tmp/yourapplication-fcgi.sock;
}
Запуск процессов FastCGI

Поскольку Nginx и другие серверы не загружают приложения FastCGI, это нужно сделать самостоятельно. Процессами FastCGI может управлять программа Supervisor. Можно поискать другие диспетчеры процессов FastCGI или написать сценарий для запуска файла .fcgi во время загрузки, например, с помощью сценария SysV init.d. В качестве временного решения может подойти запуск сценария .fcgi из программы GNU screen. Обратитесь к странице руководства screen за более подробной информацией, однако стоит заметить, что после перезагрузки системы запуск придётся повторять вручную:
$ screen
$ /var/www/yourapplication/yourapplication.fcgi
Отладка

На большинстве веб-серверов становится всё труднее отлаживать приложения FastCGI. Довольно часто единственное, о чём сообщают журналы сервера, - это о неожиданном окончании заголовков. Для отладки приложения единственное подходящее средство диагностики - это переключиться на нужного пользователя и запустить приложение вручную.

В следующем примере предполагается, что приложение называется application.fcgi, а веб-сервер работает от имени пользователя www-data:
$ su www-data
$ cd /var/www/yourapplication
$ python application.fcgi
Traceback (most recent call last):
File "yourapplication.fcgi", line 4, in <module>
ImportError: No module named yourapplication
В данном случае ошибка вызвана тем, что yourapplication не найден в путях поиска python. Обычно это происходит по одной из следующих причин:
  • Указаны относительные пути, которые не работают относительно текущего каталога.
  • Выполнение программы зависит от переменных окружения, которые не заданы для веб-сервера.
  • Используется интерпретатор python другой версии.
Примечания переводчика

В случае настройки Lighttpd не нужно писать никаких сценариев SysV init.d, потому что:

1. Lighttpd может сам управлять FastCGI-процессами на локальном компьютере, самостоятельно порождая необходимое их количество (с учётом настроенного лимита),

2. в рамках проекта Lighttpd разрабатывается собственный диспетчер процессов FastCGI - spawn-fcgi, который не настолько продвинут, чтобы регулировать количество необходимых процессов, но по крайней мере указанное количество процессов запустить и поддерживать сможет.

Обычно spawn-fcgi применяется в тех случаях, когда приложение FastCGI работает на отдельном от веб-сервера компьютере или нужно запустить приложение от имени другого пользователя, например, для изоляции друг от друга приложений разных пользователей, работающих на одном сервере. Например, так: Настройка FastCGI и PHP с индивидуальными правами пользователей.

И, наконец, никто не мешает использовать spawn-fcgi совместно с nginx.

Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.

воскресенье, 23 июня 2013 г.

Настройка сканера

В начале марта у меня сломался сканер Genius ColorPage-Slim 1200 USB2 - стал заедать шаговый мотор, движущий каретку. Сканер этот был куплен в те времена, когда я ещё не помышлял о том, чтобы поставить на свой домашний компьютер Linux. В SANE этот сканер не поддерживался и не поддерживается до сих пор.

Хотелось подобрать сканер с CCD-матрицей за приемлемые деньги и который поддерживался бы SANE. Поиски на сайтах местных компьютерных магазинов результатов не принесли - не удалось найти вообще ни одного CCD-сканера, который поддерживался бы SANE. С CIS-сканерами всё оказалось гораздо лучше - один из самых дешёвых и ходовых сканеров поддерживался SANE. Я решил, что это даже к лучшему: он дешевле, легче и компактнее, не требует внешнего блока питания, довольствуясь питанием по USB-кабелю.

Выбор пал на сканер Canon CanoScan LiDE 110:


Настройка сканера очень проста и фактически не требует особых описаний. Нужно лишь поставить какую-нибудь программу для сканирования и добавить пользователей, которые будут пользоваться сканером, в группу scanner. Я остановил свой выбор на программе Simple Scan (пакет simple-scan), хотя вам может понравиться XSane (пакет xsane):
# apt-get install simple-scan
# usermod -aG scanner stupin
После добавления пользователя может потребоваться завершить сеанс добавленного пользователя и/или начать новый, чтобы можно было начать сканировать.

Диалог настройки сканирования Simple Scan:


Выбор вида сканирования:


Обрезка листа:


Может быть и вообще не стоило писать эту заметку, но я всё же, спустя три месяца, решил об этом написать. Причина простая - это было последнее устройство, которое не поддерживалось Linux'ом. Раньше Windows был мне нужен только ради этого устройства, теперь же исчезла последняя причина для того, чтобы хотя бы изредка загружать его.

воскресенье, 16 июня 2013 г.

Настройка mod_wsgi (Apache) для Flask

Перевод статьи: mod_wsgi (Apache)

Если вы используете веб-сервер Apache и задумались об использовании mod_wsgi.

Предварительная проверка

Удостоверьтесь, что вызовы app.run() в файле приложения находятся внутри блока if __name__ == '__main__': или вынесены в отдельный файл. Просто убедитесь в отсутствии подобных вызовов, потому что если вы решили воспользоваться mod_wsgi для запуска приложения, то запускать локальный сервер WSGI не нужно.

Установка mod_wsgi

Если mod_wsgi ещё не установлен, его можно установить с помощью менеджера пакетов или собрать самостоятельно. В инструкции по установке mod_wsgi описывается установка из исходных текстов в UNIX-системах.

Если вы используете Ubuntu/Debian, можно воспользоваться apt-get:
# apt-get install libapache2-mod-wsgi
На FreeBSD mod_wsgi можно установить сборкой из порта www/mod_wsgi или при помощи pkg_add:
# pkg_add -r mod_wsgi
Если используется pkgsrc, можно установить mod_wsgi, собрав из пакета www/ap2-wsgi.

Если случится ошибка сегментации дочернего процесса после первой перезагрузки apache, можно спокойно проигнорировать её. Просто перезапустите сервер.

Создание файла .wsgi

Для запуска приложения нужен файл yourapplication.wsgi. Этот файл содержит код, выполняемый mod_wsgi для получения объекта приложения. Объект с именем application в этом файле будет использоваться в качестве приложения.

Для большинства приложений будет достаточно такого файла:
from yourapplication import app as application
Если у вас нет фабричной функции для создания приложений, но есть экземпляр-одиночка, можно просто импортировать его как приложение.

Сохраните этот файл где-нибудь, где сможете его найти (например, в /var/www/yourapplication) и удостоверьтесь, что yourapplication и все используемые им библиотеки находятся в списке путей загрузки python. Если вы не хотите делать его общедоступным для всей системы, воспользуйтесь виртуальным экземпляром python. Помните, что при этом вам нужно будет установить ваше приложение внутрь virtualenv. Или можно отредактировать переменную path внутри .wsgi перед импортом:
import sys
sys.path.insert(0, '/path/to/the/application')
Настройка Apache

Наконец, нужно создать файл с настройками Apache для запуска приложения. В следующем примере мы говорим mod_wsgi выполнить приложение от имени отдельного пользователя в целях безопасности:
<VirtualHost *>
    ServerName example.com
    WSGIDaemonProcess yourapplication user=user1 group=group1 threads=5
    WSGIScriptAlias / /var/www/yourapplication/yourapplication.wsgi
    <Directory /var/www/yourapplication>
        WSGIProcessGroup yourapplication
        WSGIApplicationGroup %{GLOBAL}
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
Замечание: WSGIDaemonProcess не реализован в Windows и Apache не запустится с указанной выше конфигурацией. В системе Windows эти строки нужно удалить:
<VirtualHost *>
    ServerName example.com
    WSGIScriptAlias / C:\yourdir\yourapp.wsgi
    <Directory C:\yourdir>
        Order deny,allow
        Allow from all
    </Directory>
</VirtualHost>
За более подробной информацией обратитесь к wiki-странице mod_wsgi.

Решение проблем

Если приложение не запускается, попробуйте следующие решения:
  • Проблема: приложение не запускается, в журнале ошибок появляется сообщение SystemExit ignored

    Произошёл вызов app.run() в файле вашего приложения, в котором не было предохранительного условия if __name__ == '__main__'. Либо удалите из файла этот вызов run(), либо поместите его в отдельный файл run.py, либо поместите его в подобный блок if.
  • Проблема: приложение сообщает об ошибках доступа

    Возможно это вызвано тем, что ваше приложение работает от неправильного пользователя. Проверьте, что каталоги, к которым необходим доступ из приложения, имеют правильные разрешения, а приложение запущено от правильного пользователя (параметры user и group в директиве WSGIDaemonProcess).
  • Проблема: приложение завершается с выводом сообщения об ошибке

    Помните, что mod_wsgi запрещает делать что-либо с sys.stdout и sys.stderr. Можно выключить эту защиту, прописав в конфигурации следующую настройку:
    WSGIRestrictStdout Off
    Или можно заменить стандартный вывод в файле .wsgi на другой поток:
    import sys
    sys.stdout = sys.stderr
  • Проблема: доступ к ресурсам приводит к ошибкам ввода-вывода

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

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

Чтобы облегчить работу инструментов установки, можно включить поддержку автоматической перезагрузки. Когда файл .wsgi изменится, mod_wsgi перезагрузит все процессы демона.

Для этого просто добавьте следующие директивы в раздел Directory:
WSGIScriptReloading On
Работа с виртуальными окружениями

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

Добавьте следующие строки в начало файла .wsgi:
activate_this = '/path/to/env/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))
Эти строки настроят пути загрузки в соответствии с настройками виртуального окружения. Помните, что это должен быть абсолютный путь.

Примечания переводчика

Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.

воскресенье, 9 июня 2013 г.

Большие приложения во Flask

Перевод статьи: Larger Applications

В больших приложениях лучше использовать пакеты вместо модулей. Это очень просто. Представьте, что небольшое приложение выглядит так:
/yourapplication
    /yourapplication.py
    /static
        /style.css
    /templates
        layout.html
        index.html
        login.html
        ...
Простые пакеты

Чтобы преобразовать его в чуть большее, просто создайте новый каталог приложения внутри существующего и поместите всё в него. Переименуйте yourapplication.py в __init__.py. (Убедитесь, что удалили все файлы .pyc, иначе скорее всего оно перестанет работать).

У вас должно получиться что-то такое:
/yourapplication
    /yourapplication
        /__init__.py
        /static
            /style.css
        /templates
            layout.html
            index.html
            login.html
            ...
Но как теперь запустить приложение? Простой запуск python yourapplication/__init__.py не сработает. Скажем так, Python не хочет запускать модули в пакете, как программы. Но это не проблема, просто добавим во внутренний каталог yourapplication новый файл runserver.py со следующим содержимым:
from yourapplication import app
app.run(debug=True)
Что это нам даст? Теперь мы можем реструктурировать приложение и поделить его на несколько модулей. Единственное, о чём нужно помнить, это:
  1. Создание приложения Flask должно происходить в файле __init__.py. Так каждый модуль сможет безопасно импортировать его, а переменная __name__ примет значение имени соответствующего пакета.
  2. Все функции представлений, к которым применён декоратор route(), должны быть импортированы в файл __init__.py. Не сам объект, но модуль с ними. Импорт модуля представлений производится после создания объекта.
Вот пример __init__.py:
from flask import Flask
app = Flask(__name__)

import yourapplication.views
При этом views.py должен выглядеть так:
from yourapplication import app
@app.route('/')
def index():
    return 'Hello World!'
В итоге должно получиться что-то вроде этого:
/yourapplication
    /runserver.py
    /yourapplication
        /__init__.py
        /views.py
        /static
            /style.css
        /templates
            layout.html
            index.html
            login.html
            ...
Взаимный импорт

Каждый Python-программист его ненавидит, но мы его добавили: два модуля зависят друг от друга. В данном случае views.py зависит от __init__.py. Мы предостерегаем вас от подобного приёма, но здесь он оправдан. Причина заключается в том, что мы на самом деле не используем представления в __init__.py, а просто убеждаемся в том, что модуль импортирован и делаем это в конце файла.

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

Работа с Blueprint'ами

Если у вас получаются большие приложения, рекомендуется поделить их на меньшие группы, в которых каждая из групп реализуется при помощи blueprint'ов. За общим введением в тему обратитесь к главе документации Модульные приложения с использованием Blueprint'ов.

Примечания переводчика

Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.

воскресенье, 2 июня 2013 г.

SQLAlchemy во Flask

Перевод статьи: SQLAlchemy in Flask

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

Есть четыре обычных способа использования SQLAlchemy. Остановимся на каждом из них подробнее:

Расширение Flask-SQLAlchemy

Поскольку SQLAlchemy - это обобщённый слой абстракции над базами данных и объектно-реляционное отображение, требующее предварительной настройки, существует расширение Flask, делающее всё необходимое за вас. Если нужно быстро начать работу, рекомендуем воспользоваться им.

Расширение Flask-SQLAlchemy можно скачать из PyPI.

Declarative

Расширение declarative в SQLAlchemy - это один из наиболее частых способов использования SQLAlchemy. Оно позволяет вам определять таблицы и модели одновременно, примерно так, как это делается в Django. В дополнение к следующему тексту рекомендуется обратиться к официальной документации по расширению declarative.

Вот пример модуля database.py для приложения:
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()

def init_db():
    # Здесь нужно импортировать все модули, где могут быть определены модели,
    # которые необходимым образом могут зарегистрироваться в метаданных. 
    # В противном случае их нужно будет импортировать до вызова init_db()
    import yourapplication.models
    Base.metadata.create_all(bind=engine)
Для определения собственных моделей наследуйте от класса Base, который создан вышеприведённым кодом. Если вы удивлены, почему в этом примере не нужно заботиться о потоках (как мы делали в примере для SQLite3 с объектом g выше), то это потому что SQLAlchemy делает это самостоятельно при помощи scoped_session.

Чтобы использовать SQLAlchemy в приложении декларативным образом, необходимо поместить в модуль вашего приложения следующий код. Flask автоматически удалит сеанс базы данных в конце запроса:
from yourapplication.database import db_session

@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()
Вот пример модели (поместите его, например, в models.py):
from sqlalchemy import Column, Integer, String
from yourapplication.database import Base

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String(50), unique=True)
    email = Column(String(120), unique=True)

    def __init__(self, name=None, email=None):
        self.name = name
        self.email = email

    def __repr__(self):
        return '<User %r>' % (self.name)
Для создания базы данных можно воспользоваться функцией init_db:
>>> from yourapplication.database import init_db
>>> init_db()
Вот так можно добавить новые записи в базу данных:
>>> from yourapplication.database import db_session
>>> from yourapplication.models import User
>>> u = User('admin', 'admin@localhost')
>>> db_session.add(u)
>>> db_session.commit()
Пример запроса:
>>> User.query.all()
[<User u'admin'>]
>>> User.query.filter(User.name == 'admin').first()
<User u'admin'>
Ручное объектно-реляционное отображение

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

Вот пример модуля database.py:
from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
metadata = MetaData()
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))
def init_db():
    metadata.create_all(bind=engine)
Как и в декларативном случае, вам необходимо закрывать сеанс после каждого запроса. Поместите следующие строки в модуль вашего приложения:
from yourapplication.database import db_session

@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()
Вот пример таблицы и модели (поместите их в models.py):
from sqlalchemy import Table, Column, Integer, String
from sqlalchemy.orm import mapper
from yourapplication.database import metadata, db_session

class User(object):
    query = db_session.query_property()

    def __init__(self, name=None, email=None):
        self.name = name
        self.email = email

    def __repr__(self):
        return '<User %r>' % (self.name)

users = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String(50), unique=True),
    Column('email', String(120), unique=True)
)
mapper(User, users)
Запрос и вставка записей делается точно так же, как в примере выше.

Слой абстракции над SQL

Если вы хотите использовать только слой абстракции к базам данных (и SQL), вам потребуется только объект engine:
from sqlalchemy import create_engine, MetaData

engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
metadata = MetaData(bind=engine)
Теперь можно объявить таблицы в коде, как в примере выше или автоматически загрузить их:
users = Table('users', metadata, autoload=True)
Чтобы вставить данные, вы можете воспользоваться методом insert. Прежде чем совершить транзакцию, необходимо сначала получить подключение:
>>> con = engine.connect()
>>> con.execute(users.insert(), name='admin', email='admin@localhost')
SQLAlchemy автоматически подтвердит транзакцию.

Для выполнения запросов можно воспользоваться напрямую объектом engine, либо использовать подключение:
>>> users.select(users.c.id == 1).execute().first()
(1, u'admin', u'admin@localhost')
С результатом запроса можно обращаться как со словарём:
>>> r = users.select(users.c.id == 1).execute().first()
>>> r['name']
u'admin'
В метод execute() можно также передавать строки с выражениями SQL:
>>> engine.execute('select * from users where id = :1', [1]).first()
(1, u'admin', u'admin@localhost')
За более подробной информацией о SQLAlchemy обратитесь к вебсайту.

Примечания переводчика

В сети можно найти учебник по использованию SQLAlchemy: SQLAlchemy - викиучебник.

Этот и другие переводы можно найти на сайте проекта перевода документации по Flask. Автор проекта - Виталий Кузьмин aka ferm32.