[Перевод] Brython: Python в вашем браузере (ч.3)

Часть 1 • Часть 2 • Часть 3 • Часть 4

Взаимодействие с JavaScript

Brython позволяет Python-коду взаимодействовать с кодом JavaScript. Наиболее распространенный шаблон — доступ к JavaScript из Brython. Обратный вариант, хотя и возможен, не распространен. Вы увидите пример вызова функции Python в JavaScript в разделе Модульные тесты JavaScript.

JavaScript

До этого момента вы сталкивались с несколькими сценариями, в которых код Python взаимодействовал с кодом JavaScript. В частности, вы могли отобразить окно сообщения, вызвав browser.alert ().

Вы можете увидеть alert в действии в следующих трех примерах, запущенных в консоли Brython, а не в стандартной оболочке интерпретатора CPython:

>>> import browser
>>> browser.alert("Real Python")

Или использовать window:

>>> from browser import window
>>> window.alert("Real Python")

Или использовать this:

>>> from javascript import this
>>> this().alert("Real Python")

Благодаря новому слою, представленному Brython, а также глобальному характеру alert () и window, вы можете вызывать alert как browser.window или даже как javascript.this.

Вот основные модули Brython, обеспечивающие доступ к функциям JavaScript:

Модули

Контекст

Примеры

browser

Содержит встроенные имена и модули

browser.alert ()

browser.document

Доступ к DOM

document.getElementById («element-id»)

document[«element-id»]

browser.html

Создает HTML-элементы

html.H1(«This is the title»)

browser.window

Доступ к функциям Window и объектам

window.navigator

window.frames

javascript.JSON.parse ()

javascript.this ()

javascript.JSON.parse ()

В дополнение к функциям JavaScript и API, доступным в браузере, вы также можете получить доступ к функциям JavaScript, которые вы написали. Следующий пример демонстрирует, как получить доступ к пользовательской функции JavaScript из Brython:



  
    
    
    
  
  
    
  











Вот как это работает:

  • Строка 9 определяет пользовательскую функцию myMessageBox () в блоке JavaScript.

  • Строка 17 вызывает myMessageBox ().

Вы можете использовать ту же функцию для доступа к библиотекам JavaScript. Вы увидите, как это сделать, в разделе Web UI Framework, где вы будете взаимодействовать с Vue.js, популярным UI-фреймворком.

Веб-API браузера

Браузеры предоставляют веб-API, к которым можно получать доступ из JavaScript, и Brython имеет доступ к тем же API. В этом разделе вы расширите калькулятор Base64 для хранения данных между перезагрузками страницы.

Веб-API, предоставляющий эту функцию, — это Web Storage API. Он включает два механизма:

  1. sessionStorage

  2. localStorage

Будем использовать localStorage в следующем примере.

Как вы узнали ранее, калькулятор Base64 создает словарь, содержащий входную строку, сопоставленную с кодированным в Base64 значением этой строки. Данные сохраняются в памяти после загрузки страницы, но очищаются при ее перезагрузке. Сохранение данных в localStorage сохранит словарь между перезагрузками страницы. localStorage — это хранилище ключей и значений.

Чтобы получить доступ localStorage, вам нужно импортировать storage. Чтобы оставаться ближе к первоначальной реализации, вы загрузите и сохраните данные словаря localStorage в формате JSON. Ключом для сохранения и извлечения данных будет b64data. Измененный код включает новые импорты и функцию load_data ():

from browser.local_storage import storage
import json, base64

def load_data():
    data = storage.get("b64data")
    if data:
        return json.loads(data)
    else:
        storage["b64data"] = json.dumps({})
        return {}

load_data () выполняется при загрузке кода Python. Она извлекает данные JSON из localStorage и заполняет словарь Python, который будет использоваться для хранения данных в памяти в течение жизни страницы. Если она не находит b64data в localStorage, то создает пустой словарь для ключа b64data в localStorage и возвращает пустой словарь.

Ниже полный код Python, включая функцию load_data (). Он демонстрирует, как использовать веб-API localStorage для постоянного хранения данных, вместо временного хранения в оперативной памяти, как в предыдущей версии этого примера.

from browser import document, prompt, html, alert
from browser.local_storage import storage
import json, base64

def load_data():
    data = storage.get("b64data")
    if data:
        return json.loads(data)
    else:
        storage["b64data"] = json.dumps({})
        return {}

def base64_compute(evt):
    value = document["text-src"].value
    if not value:
        alert("You need to enter a value")
        return
    if value in b64_map:
        alert(f"'{value}' already exists: '{b64_map[value]}'")
        return
    b64data = base64.b64encode(value.encode()).decode()
    b64_map[value] = b64data
    storage["b64data"] = json.dumps(b64_map)
    display_map()

def clear_map(evt):
    b64_map.clear()
    storage["b64data"] = json.dumps({})
    document["b64-display"].clear()

def display_map():
    if not b64_map:
        return
    table = html.TABLE(Class="pure-table")
    table <= html.THEAD(html.TR(html.TH("Text") + html.TH("Base64")))
    table <= (html.TR(html.TD(key) + html.TD(b64_map[key])) for key in b64_map)
    base64_display = document["b64-display"]
    base64_display.clear()
    base64_display <= table
    document["text-src"].value = ""

b64_map = load_data()
display_map()
document["submit"].bind("click", base64_compute)
document["clear-btn"].bind("click", clear_map)

Глобальный словарь b64_map заполняется функцией load_data () при загрузке файла и обрабатывается во время вызова brython (). Когда страница перезагружается, данные извлекаются из localStorage.

Каждый раз, когда вычисляется новое значение Base64, содержимое b64_map преобразуется в JSON и сохраняется в локальном хранилище. Ключ для хранения — b64data.

Вы можете получить доступ ко всем функциям веб-API из browser и других субмодулей. Высокоуровневая документация по доступу к веб-API доступна в документации Brython. Для получения более подробной информации см. документацию веб-API, а также используйте консоль Brython для экспериментов с веб-API.

В некоторых ситуациях вам, возможно, придется выбирать между привычными функциями Python и функциями из веб-API. Например, в вышеуказанном коде вы используете Python-функцию для Base64-перекодировки base64.b64encode (), хлья можно было бы использовать JavaScript-функцию btoa ():

>>> from browser import window
>>> window.btoa("Real Python")
'UmVhbCBQeXRob24='

Можете протестировать оба варианта в онлайн-консоли. Использование window.btoa () будет работать только в контексте Brython, тогда как base64.b64encode () может быть выполнено с обычной реализацией Python, например CPython. Обратите внимание, что в версии CPython base64.b64encode () в качестве типа аргумента принимает bytearray, тогда как JavaScript-функция window.btoa () принимает строку.

Если важнее производительность, используйте JavaScript-версию.

Фреймворк Web UI

Популярные UI-фреймворки JavaScript, такие как Angular, React, Vue.js или Svelte, стали важной частью набора инструментов front-end-разработчика, и Brython легко интегрируется с некоторыми из этих фреймворков. В этом разделе вы создадите приложение с использованием Vue.js версии 3 и Brython.

Приложение, которое вы создадите, — это форма, которая вычисляет хэш строки. Вот скриншот работающей HTML-страницы:

Brython Vue.js

Brython Vue.js

body HTML-страницы декларативно определяет привязки и шаблоны:



  
    
    
    
    
    
    
    
  


  
Hash Calculator

Если вы не знакомы с Vue, то ниже будут кратко изложены несколько основных моментов. Для получения более подробной информации, обратитесь к официальной документации:

  • Директивы Vue.js — это специальные значения атрибутов с префиксом v-, которые обеспечивают динамическое поведение и сопоставление данных между значениями компонентов DOM и Vue.js:

    • v-model.trim=«input_text» привязывает входное значение к модели Vue input_text и обрезает значение.

    • v-model=«algo» привязывает значение раскрывающегося списка к algo.

    • v-for=«name in algos» привязывает значение параметра к name.

  • Шаблоны Vue обозначаются переменными, заключенными в двойные фигурные скобки. Vue.js заменяет соответствующие заполнители соответствующим значением в компоненте Vue:

    • hash_value

    • name

  • Обработчики событий обозначаются символом (@), как в @click=«compute_hash».

Соответствующий код Python описывает Vue и прикрепленную бизнес-логику:

from browser import alert, window
from javascript import this
import hashlib

hashes = {
    "sha-1": hashlib.sha1,
    "sha-256": hashlib.sha256,
    "sha-512": hashlib.sha512,
}

Vue = window.Vue

def compute_hash(evt):
    value = this().input_text
    if not value:
        alert("You need to enter a value")
        return
    hash_object = hashes[this().algo]()
    hash_object.update(value.encode())
    hex_value = hash_object.hexdigest()
    this().hash_value = hex_value

def created():
    for name in hashes:
        this().algos.append(name)
    this().algo = next(iter(hashes))

app = Vue.createApp(
    {
        "el": "#app",
        "created": created,
        "data": lambda _: {"hash_value": "", "algos": [], "algo": "", "input_text": ""},
        "methods": {"compute_hash": compute_hash},
    }
)

app.mount("#app")

Декларативная природа Vue.js отображается в HTML-файле с директивами и шаблонами Vue. Она также демонстрируется в коде Python с объявлением компонента Vue в строке 11 и строках 28–35. Эта декларативная техника связывает значения узлов DOM с данными Vue, обеспечивая реактивное поведение фреймворка.

Это устраняет часть шаблонного кода, который вам пришлось написать в предыдущем примере. Например, обратите внимание, что вам не нужно было выбирать элементы из DOM с помощью выражения вроде document[«some_id»]. Создание приложения Vue и вызов app.mount () обрабатывает сопоставление компонента Vue с соответствующими элементами DOM и привязку функций JavaScript.

В Python для доступа к полям объекта Vue необходимо сослаться на объект Vue с помощью javascript.this ():

  • Строка 14 извлекает значение поля компонента this ().input_text.

  • Строка 21 обновляет компонент данных this ().hash_value.

  • Строка 25 добавляет алгоритм в список this ().algos.

  • Строка 26 создает экземпляр this ().algo с первым ключом hashes{}.

Если это знакомство с Vue в сочетании с Brython вызвало у вас интерес, то, возможно, вам стоит ознакомиться с проектом vuepy, который предоставляет полные привязки Python для Vue.js и использует Brython для запуска Python в браузере.

WebAssembly

В некоторых ситуациях вы можете использовать WebAssembly для улучшения производительности Brython или даже JavaScript. WebAssembly или Wasm — это двоичный код, поддерживаемый всеми основными браузерами. Он может обеспечить улучшение производительности по сравнению с JavaScript в браузере и является целью компиляции для таких языков, как C, C++ и Rust. Если вы не используете Rust или Wasm, то можете пропустить этот раздел.

В следующем примере, демонстрирующем способ использования WebAssembly, вы реализуете функцию в Rust и вызовете ее из Python.

Это не претендует на звание полного руководства по Rust. Это только поверхностное описание. Для получения более подробной информации о Rust ознакомьтесь с документацией Rust.

Начните с установки Rust с помощью rustup. Для компиляции файлов Wasm вам также необходимо добавить wasm32-цель:

$ rustup target add wasm32-unknown-unknown

Создайте проект с помощью cargo, который устанавливается во время установки Rust:

$ cargo new --lib op

Данная команда создаст проект-скелет в папке с именем op. В этой папке вы найдете Cargo.toml, файл конфигурации сборки Rust, который вам нужно изменить, чтобы указать, что вы хотите создать динамическую библиотеку. Вы можете сделать это, добавив раздел [lib]:

[package]
name = "op"
version = "0.1.0"
authors = ["John "]
edition = "2018"

[lib]
crate-type=["cdylib"]

[dependencies]

Измените src/lib.rs, заменив его содержимое следующим:

#[no_mangle]
pub extern fn double_first_and_add(x: u32, y: u32) -> u32 {
    (2 * x) + y
}

Находясь в корне проекта, где расположен Cargo.toml, запустите компиляцию проекта:

$ cargo build --target wasm32-unknown-unknown

Далее создайте каталог web и index.html в нем, со следующим содержимым:





  
  



Custom Operation using Wasm + Brython

Multiply first number by 2 and add result to second number

Строка 6 выше загружает следующее main.py из того же каталога:

from browser import document, window

double_first_and_add = None

def add_rust_fn(module):
  global double_first_and_add
  double_first_and_add = module.instance.exports.double_first_and_add

def add_numbers(evt):
    nb1 = document["number-1"].value or 0
    nb2 = document["number-2"].value or 0
    res = double_first_and_add(nb1, nb2)
    document["result"].innerHTML = f"Result: ({nb1} * 2) + {nb2} = {res}"

document["submit"].bind("click", add_numbers)
window.WebAssembly.instantiateStreaming(window.fetch("op.wasm")).then(add_rust_fn)

Строки 5 и 7 — это связующее звено, позволяющее Brython получить доступ к функции Rust double_first_and_add ():

  • Строка 16 читает op.wasm используя WebAssembly, затем при загрузке Wasm-файла вызывается add_rust_fn ().

  • Строка 5 реализует add_rust_fn (), который принимает модуль Wasm в качестве аргумента.

  • Строка 7 присваивает значение double_first_and_add () локальному double_first_and_add, чтобы сделать его доступным для Python.

Находяст в каталоге web скопируйте op.wasm из target/wasm32-unknown-unknown/debug/op.wasm:

$ cp target/wasm32-unknown-unknown/debug/op.wasm web

Структура папки проекта выглядит следующим образом:

├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
├── target
│   ...
└── web
    ├── index.html
    ├── main.py
    └── op.wasm

Здесь показана структура папок проекта Rust, созданного с помощью cargo new. Для ясности target частично опущено.

Теперь запустите сервер в web:

$ python3 -m http.server
Serving HTTP on :: port 8000 (http://[::]:8000/) ...

Наконец, перейдите по URL http://localhost:8000. Браузер должен отобразить страницу следующего вида:

WASM Brython

WASM Brython

Данный проект показывает, как создать WebAssembly, который можно использовать из JavaScript или Brython. Из-за значительных накладных расходов, возникающих при создании файла Wasm, это не должно быть вашим первым подходом к решению конкретной проблемы.

Примечание: для более глубокого погружения в WebAssembly ознакомьтесь с подкастом The Real Python — выпуск 154 с Бреттом Кэнноном.

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

Другим возможным преимуществом использования Rust для генерации WebAssembly является его доступ к библиотекам, которые не существуют в Python или JavaScript. Это также может быть полезно, если вы хотите использовать библиотеку Python, написанную на C и несовместимую с Brython. Если такая библиотека существует в Rust, то вы можете рассмотреть возможность создания файла Wasm для использования ее с Brython.

Применение асинхронной разработки в Brython

Синхронное программирование — это поведение вычислений, с которым вы, возможно, наиболее знакомы. Например, при выполнении трех операторов, A, B и C, программа сначала выполняет A, затем B и, наконец, C. Каждый оператор блокирует поток программы, прежде чем передать его следующему.

Представьте себе ситуацию, при которой A будет выполнено первым, B будет вызван, но не выполнен немедленно, а затем будет выполнен C. Вы можете думать о B как об обещании быть выполненным в будущем. Поскольку B неблокируемый, он считается асинхронным. Для получения дополнительной информации об асинхронном программировании вы можете ознакомиться с Getting Started With Async Features in Python.

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

С Brython у вас есть доступ к асинхронным функциям через ряд компонентов:

По мере развития JavaScript обратные вызовы постепенно заменялись обещаниями (промисами) или асинхронными функциями. В этом руководстве вы узнаете, как использовать промисы из Brython и как использовать модули browser.ajax и browser.aio, которые используют асинхронную природу JavaScript.

Модуль asyncio из библиотеки CPython не может быть использован в контексте браузера и заменен в Brython на browser.aio.

Промисы JavaScript в Brython

==========================================
В JavaScript промис — это объект, который может дать результат когда-нибудь в будущем. Значение, полученное после завершения, будет либо значением, либо причиной ошибки.

Вот пример, иллюстрирующий, как использовать JavaScript-объект Promise из Brython. Вы можете работать с этим примером в онлайн-консоли:

>>> from browser import timer, window
>>> def message_in_future(success, error):
...   timer.set_timeout(lambda: success("Message in the future"), 3000)
...
>>> def show_message(msg):
...   window.alert(msg)
...
>>> window.Promise.new(message_in_future).then(show_message)

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

  • Строка 1 импортирует timer для установки тайм-аута и window для доступа к объекту Promise.

  • Строка 2 определяет исполнителя — функцию message_in_future (), которая возвращает сообщение при успешном выполнении обещания по истечении времени ожидания.

  • Строка 5 определяет функцию show_message (), которая отображает оповещение.

  • Строка 8 создает промис с исполнителем, связанным с блоком then, что позволяет получить доступ к результату промиса.

В приведенном выше примере тайм-аут искусственно имитирует долго работающую функцию. Реальное использование обещания может включать сетевой вызов. Через 3 секунды промис успешно завершается со значением «Message in the future».

Если функция-исполнитель message_in_future () обнаруживает ошибку, то она может вызвать error () с причиной ошибки в качестве аргумента. Вы можете реализовать это с помощью нового цепочечного метода, .catch (), объекта Promise, следующим образом:

>>> window.Promise.new(message_in_future).then(show_message).catch(show_message)

Поведение успешного выполнения промиса можно увидеть на следующем изображении:

Обещание в консоли Brython

Обещание в консоли Brython

При запуске кода в консоли вы увидите, что сначала создается объект Promise, а затем, по истечении времени ожидания, отображается окно сообщения.

Ajax в Brython

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

В Brython модуль browser.ajax предоставляет HTTP-функции, такие как get () и post (), которые по умолчанию являются асинхронными. Эти функции принимают параметр blocking, который можно установить в значение True, чтобы сделать функцию синхронной.

Чтобы вызвать HTTP GET асинхронно, выполните ajax.get () следующий вызов:

ajax.get(url, oncomplete=on_complete)

Чтобы получить API в режиме блокировки, установите параметр blocking в True:

ajax.get(url, blocking=True, oncomplete=on_complete)

Следующий код показывает разницу между выполнением блокирующего вызова Ajax и неблокирующего вызова Ajax:

from browser import ajax, document
import javascript

def show_text(req):
    if req.status == 200:
        log(f"Text received: '{req.text}'")
    else:
        log(f"Error: {req.status} - {req.text}")

def log(message):
    document["log"].value += f"{message} \n"

def ajax_get(evt):
    log("Before async get")
    ajax.get("/api.txt", oncomplete=show_text)
    log("After async get")

def ajax_get_blocking(evt):
    log("Before blocking get")
    try:
        ajax.get("/api.txt", blocking=True, oncomplete=show_text)
    except Exception as exc:
        log(f"Error: {exc.__name__} - Did you start a local web server?")
    else:
        log("After blocking get")

document["get-btn"].bind("click", ajax_get)
document["get-blocking-btn"].bind("click", ajax_get_blocking)

Приведенный выше код иллюстрирует оба поведения: синхронное и асинхронное:

  • Строка 13 определяет функцию ajax_get (), которая извлекает текст из удаленного файла с помощью ajax.get (). По умолчанию ajax.get () работает асинхронно. Функция ajax_get () возвращает управление, и функция show_text (), привязанная к параметру oncomplete, вызывается после получения удаленного файла /api.txt.

  • Строка 18 определяет функцию ajax_get_blocking (), которая демонстрирует, как использовать ajax.get () с блокирующим поведением. В этом случае show_text () вызывается до возврата ajax_get_blocking ().

При запуске полного примера и нажатии Async Get и Blocking Get вы увидите следующий экран:

Браузер Ajax

Браузер Ajax

Как видно, в первом сценарии ajax_get () выполняется полностью, а результат вызова API происходит асинхронно. Во второй ситуации результат вызова API отображается перед возвратом из ajax_get_blocking ().

Асинхронный ввод-вывод в Brython

С asyncio, Python 3.4 начал предоставлять новые асинхронные возможности. В Python 3.5 асинхронная поддержка была расширена синтаксисом async/await. Из-за несовместимости с циклом событий браузера, Brython реализует browser.aio в качестве замены стандартному asyncio.

Brython-модуль browser.aio и Python-модуль asyncio поддерживают использование ключевых слов async и await и имеют общие функции, такие как run () и sleep (). Оба модуля реализуют другие различные функции, которые относятся к их соответствующим контекстам выполнения, среде контекста CPython для asyncio, и среде браузера для browser.aio.

Сопрограммы

Вы можете использовать run () и sleep () для создания сопрограмм (корутин). Чтобы проиллюстрировать поведение сопрограмм, реализованных в Brython, вы реализуете вариант примера сопрограммы, доступного в документации CPython:

from browser import aio as asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

За исключением первой строки с import, код такой же, как и в документации CPython. Он демонстрирует использование ключевых слов async и await, а также показывает в действии run () и sleep ():

  • Строка 1 использует asyncio как псевдоним для browser.aio. Хотя это и накладывается на aio, такой подход позволяет сохранить код ближе к примеру из документации Python для облегчения сравнения.

  • Строка 4 объявляет сопрограмму say_after (). Обратите внимание на использование async.

  • Строка 5 вызывается asyncio.sleep () с помощью await так, что текущая функция передаст управление другой функции до завершения sleep ().

  • В строке 8 объявляется еще одна сопрограмма, которая сама дважды вызовет сопрограмму say_after ().

  • Строка 9 вызывает run () — неблокируемую функцию, которая принимает сопрограмму — в данном примере main () — в качестве аргумента.

Обратите внимание, что в контексте браузера aio.run () использует внутренний цикл событий JavaScript. Это отличается от связанной функции asyncio.run () в CPython, которая полностью управляет циклом событий.

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

Асинхронный ввод-вывод в Brython

Асинхронный ввод-вывод в Brython

Сначала выполняется скрипт, затем отображается «hello», а затем отображается «world».

Дополнительную информацию о сопрограммах в Python можно найти в статье Асинхронный ввод-вывод в Python: полное пошаговое руководство.

Общие концепции асинхронного ввода-вывода применимы ко всем платформам, охватывающим этот шаблон. В JavaScript цикл событий является неотъемлемой частью среды, тогда как в CPython это то, что управляется с помощью функций, предоставляемых asyncio.

Вышеприведенный пример был целенаправленным упражнением, чтобы сохранить код в точности таким, как показано в примере документации Python. При кодировании в браузере с Brython рекомендуется явно использовать browser.aio, как вы увидите в следующем разделе.

Веб-специфические функции

Чтобы выполнить асинхронный вызов API, как в предыдущем разделе, можно написать функцию следующего вида:

async def process_get(url):
    req = await aio.get(url)

Обратите внимание на использование ключевых слов async и await. Функцию, использующую вызов с await, необходимо определить как async. Во время выполнения этой функции, при достижении вызова await aio.get (url), функция возвращает управление основному циклу событий, ожидая завершения сетевого вызова aio.get (). Остальная часть выполнения программы не блокируется.

Вот пример того, как вызвать process_get ():

aio.run(process_get("/some_api"))

Функция aio.run () выполняет сопрограмму process_get (). Она неблокируемая.

Более полный пример кода показывает, как использовать ключевые слова async и await, и как aio.run () с aio.get () дополняют друг друга:

from browser import aio, document
import javascript

def log(message):
    document["log"].value += f"{message} \n"

async def process_get(url):
    log("Before await aio.get")
    req = await aio.get(url)
    log(f"Retrieved data: '{req.data}'")

def aio_get(evt):
    log("Before aio.run")
    aio.run(process_get("/api.txt"))
    log("After aio.run")

document["get-btn"].bind("click", aio_get)

Как и в последних версиях Python 3, вы можете использовать ключевые слова async и await:

  • Строка 7 определяет process_get () с ключевым словом async.

  • Строка 9 вызывается aio.get () с ключевым словом await. Использование await требует чтобы охватывающая функция была определена с помощью async.

  • В строке 14 показано, как использовать aio.run (), который принимает в качестве аргумента вызываемую async-функцию.

Для запуска полного примера вам нужно запустить веб-сервер. Вы можете запустить веб-сервер разработки Python с помощью python3 -m http.server. Он запускает локальный веб-сервер на порту 8000 и страницу по умолчанию index.html:

Браузер Aio

Браузер Aio

На снимке экрана показана последовательность шагов, выполняемых после нажатия на Async Get. Сочетание использования модуля aio и ключевых слов async и await показывает, как можно использовать асинхронную модель программирования, которую продвигает JavaScript.

Далее…

© Habrahabr.ru