contextvars — Переменные контекста
Этот модуль предоставляет API для управления состоянием, локальным для контекста, его хранения и доступа к нему. Класс ContextVar используется для объявления и работы с переменными контекста. Функцию copy_context() и класс Context следует использовать для управления текущим контекстом в асинхронных фреймворках.
Менеджерам контекста, содержащим состояние, следует использовать переменные контекста вместо threading.local(), чтобы при использовании в параллельном коде их состояние неожиданно не распространялось на другой код.
Дополнительные сведения см. также в PEP 567.
Добавлено в версии 3.7.
Переменные контекста
-
class contextvars.ContextVar(name[, *, default]) -
Этот класс используется для объявления новой переменной контекста, например:
var: ContextVar[int] = ContextVar('var', default=42)Обязательный параметр name используется для интроспекции и отладки.
Необязательный именованный параметр default возвращается методом
ContextVar.get(), если в текущем контексте не найдено значение переменной.Важно: Переменные контекста следует создавать на верхнем уровне модуля, а не в замыканиях. Объекты
Contextхранят сильные ссылки на переменные контекста, из-за чего сборщик мусора не может корректно освобождать их.-
name -
Имя переменной. Это свойство доступно только для чтения.
Добавлено в версии 3.7.1.
-
get([default]) -
Возвращает значение переменной контекста для текущего контекста.
Если в текущем контексте нет значения переменной, метод:
- возвращает значение аргумента метода default, если он задан; или
- возвращает значение по умолчанию для переменной контекста, если оно было задано при её создании; или
- вызывает исключение
LookupError.
-
set(value) -
Устанавливает новое значение переменной контекста в текущем контексте.
Обязательный аргумент value — новое значение переменной контекста.
Возвращает объект
Token, который можно использовать для восстановления прежнего значения переменной с помощью методаContextVar.reset().
-
reset(token) -
Сбрасывает значение переменной контекста до значения, которое она имела до вызова
ContextVar.set(), создавшего token.Например:
var = ContextVar('var') token = var.set('new value') # code that uses 'var'; var.get() returns 'new value'. var.reset(token) # After the reset call the var has no value again, so # var.get() would raise a LookupError.
-
-
class contextvars.Token -
Объекты Token возвращаются методом
ContextVar.set(). Их можно передать методуContextVar.reset(), чтобы вернуть переменной значение, которое она имела до соответствующего вызова set.-
var -
Свойство доступно только для чтения. Указывает на объект
ContextVar, создавший токен.
-
old_value -
Свойство доступно только для чтения. Содержит значение переменной до вызова метода
ContextVar.set(), создавшего токен. Если до вызова значение переменной не было установлено, свойство указывает наToken.MISSING.
-
MISSING -
Маркерный объект, используемый свойством
Token.old_value.
-
Ручное управление контекстом
-
contextvars.copy_context() -
Возвращает копию текущего объекта
Context.Следующий фрагмент получает копию текущего контекста и выводит все заданные в нём переменные и их значения:
ctx: Context = copy_context() print(list(ctx.items()))
Сложность функции составляет O(1): она работает одинаково быстро и для контекстов с небольшим числом переменных, и для контекстов с большим их числом.
-
class contextvars.Context -
Сопоставление объектов
ContextVarsс их значениями.Context()создаёт пустой контекст без значений. Чтобы получить копию текущего контекста, используйте функциюcopy_context().У каждого потока есть собственный стек объектов
Context. Текущий контекст — это объектContext, находящийся на вершине стека текущего потока. Все объектыContextв стеках считаются активными.Вход в контекст, который можно выполнить вызовом его метода
run(), делает этот контекст текущим, помещая его на вершину стека контекстов текущего потока.Выход из текущего контекста, который происходит при возврате из обратного вызова, переданного методу
run(), восстанавливает прежний текущий контекст, снимая текущий контекст с вершины стека контекстов.Поскольку у каждого потока свой стек контекстов, объекты
ContextVarведут себя подобноthreading.local(), когда значения присваиваются в разных потоках.Попытка войти в уже активный контекст, в том числе в контекст, активированный в другом потоке, вызывает исключение
RuntimeError.После выхода из контекста в него можно войти повторно (из любого потока).
Все изменения значений
ContextVarс помощью методаContextVar.set()записываются в текущий контекст. МетодContextVar.get()возвращает значение, связанное с текущим контекстом. При выходе из контекста фактически отменяются все изменения переменных контекста, сделанные во время его активности (при необходимости значения можно восстановить, повторно войдя в контекст).Класс Context реализует интерфейс
collections.abc.Mapping.-
run(callable, *args, **kwargs) -
Входит в контекст, выполняет
callable(*args, **kwargs), а затем выходит из контекста. Возвращает значение, возвращённое объектом callable, или передаёт исключение дальше, если оно возникло.Пример:
import contextvars var = contextvars.ContextVar('var') var.set('spam') print(var.get()) # 'spam' ctx = contextvars.copy_context() def main(): # 'var' was set to 'spam' before # calling 'copy_context()' and 'ctx.run(main)', so: print(var.get()) # 'spam' print(ctx[var]) # 'spam' var.set('ham') # Now, after setting 'var' to 'ham': print(var.get()) # 'ham' print(ctx[var]) # 'ham' # Any changes that the 'main' function makes to 'var' # will be contained in 'ctx'. ctx.run(main) # The 'main()' function was run in the 'ctx' context, # so changes to 'var' are contained in it: print(ctx[var]) # 'ham' # However, outside of 'ctx', 'var' is still set to 'spam': print(var.get()) # 'spam'
-
copy() -
Возвращает поверхностную копию объекта контекста.
- var in context
-
Возвращает
True, если в context задано значение для var; в противном случае возвращаетFalse.
- context[var]
-
Возвращает значение переменной
ContextVarvar. Если переменная не задана в объекте контекста, возникает исключениеKeyError.
-
get(var[, default]) -
Возвращает значение для var, если оно задано в объекте контекста. В противном случае возвращает default. Если default не задан, возвращает
None.
- iter(context)
-
Возвращает итератор по переменным, хранящимся в объекте контекста.
- len(proxy)
-
Возвращает количество переменных, заданных в объекте контекста.
-
keys() -
Возвращает список всех переменных в объекте контекста.
-
values() -
Возвращает список значений всех переменных в объекте контекста.
-
items() -
Возвращает список пар из двух элементов, содержащих все переменные и их значения в объекте контекста.
-
Поддержка asyncio
Переменные контекста изначально поддерживаются в asyncio и готовы к использованию без дополнительной настройки. Например, ниже приведён простой эхо-сервер, использующий переменную контекста, чтобы адрес удалённого клиента был доступен задаче, обрабатывающей этого клиента:
import asyncio
import contextvars
client_addr_var = contextvars.ContextVar('client_addr')
def render_goodbye():
# The address of the currently handled client can be accessed
# without passing it explicitly to this function.
client_addr = client_addr_var.get()
return f'Good bye, client @ {client_addr}\r\n'.encode()
async def handle_request(reader, writer):
addr = writer.transport.get_extra_info('socket').getpeername()
client_addr_var.set(addr)
# In any code that we call is now possible to get
# client's address by calling 'client_addr_var.get()'.
while True:
line = await reader.readline()
print(line)
if not line.strip():
break
writer.write(b'HTTP/1.1 200 OK\r\n') # status line
writer.write(b'\r\n') # headers
writer.write(render_goodbye()) # body
writer.close()
async def main():
srv = await asyncio.start_server(
handle_request, '127.0.0.1', 8081)
async with srv:
await srv.serve_forever()
asyncio.run(main())
# To test it you can use telnet or curl:
# telnet 127.0.0.1 8081
# curl 127.0.0.1:8081
© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/contextvars.html