Конкурентность с Eventlet¶
Домашняя страница Eventlet описывает его как библиотеку параллельных сетей для Python, которая позволяет вам изменить то, как вы выполняете свой код, а не то, как вы его пишете.
- Он использует epoll(4) или libevent для highly scalable non-blocking I/O.
- Coroutines убедитесь, что разработчик использует блокирующий стиль программирования, который похож на потоковый, но обеспечивает преимущества неблокирующего ввода-вывода.
- Диспетчеризация событий является неявной: это означает, что вы можете легко использовать Eventlet из интерпретатора Python или в качестве небольшой части более крупного приложения.
Celery поддерживает Eventlet в качестве альтернативной реализации пула исполнения и в некоторых случаях превосходит prefork. Однако необходимо следить за тем, чтобы одна задача не блокировала цикл событий слишком долго. Как правило, операции, привязанные к процессору, не очень хорошо сочетаются с Eventlet. Также обратите внимание, что некоторые библиотеки, обычно с расширениями C, не могут быть monkeypatched и поэтому не могут получить преимущества от использования Eventlet. Если вы не уверены, обратитесь к их документации. Например, pylibmc не позволяет работать с Eventlet, а psycopg2 позволяет, если обе они являются библиотеками с расширениями C.
Пул prefork может использовать несколько процессов, но их количество часто ограничено несколькими процессами на процессор. С Eventlet вы можете эффективно порождать сотни или тысячи зеленых потоков. В неофициальном тесте с системой feed hub пул Eventlet мог получать и обрабатывать сотни фидов каждую секунду, в то время как пул prefork тратил 14 секунд на обработку 100 фидов. Обратите внимание, что это одно из приложений, в котором асинхронный ввод-вывод особенно хорош (асинхронные HTTP-запросы). Вам может понадобиться сочетание рабочих Eventlet и prefork, и распределяйте задачи в зависимости от совместимости или того, что лучше работает.
Включение эвентлета¶
Вы можете включить пул эвентлетов, используя опцию celery worker -P worker.
$ celery -A proj worker -P eventlet -c 1000
Примеры¶
Смотрите каталог Eventlet examples в дистрибутиве Celery для некоторых примеров, использующих поддержку Eventlet.
Особенности асинхронности в Python
Привет, Хабр! Меня зовут Николай Нагорный, я работаю в Росбанке над платформой Advisors’ Axiom. В этом посте я подробно расскажу о важной фиче, которая появилась в Python 3.5 — асинхронности. Затрону основные концепции и инструменты, приведу примеры кода. Пост будет полезен новичкам для понимания основ асинхронности и, может, даже опытным разработчикам в поиске новых идей и подходов.

Начнем с определения. Асинхронность — это парадигма программирования, которая позволяет выполнять несколько задач одновременно, не дожидаясь завершения каждой из них; важный инструмент для решения проблем с производительностью в веб-приложениях и серверных технологиях. С момента появления асинхронности в Python сразу было доступно несколько способов реализации асинхронного кода. Чаще всего для асинхронных операций в Python используют библиотеки async/await и asyncio. Также асинхронность может быть использована для веб-приложений в сочетании с фреймворками, например с Django, Flask или Fast API.
Асинхронность в чистом Python
Один из способов реализации асинхронности в Python — декоратор @asyncio.coroutine. Вот функция-корутина, которая выполняет ожидание в течение некоторого времени:
import asyncio # импорт библиотеки @asyncio.coroutine # декоратор def my_coroutine(seconds): print ('Starting coroutine') yield from asyncio.sleep(seconds) # возвращаем результат print ('Finishing coroutine') loop = asyncio.get_event_loop () # создаем объект loop.run_until_complete(my_coroutine (2)) # запускаем loop.close () # закрываем
Другой, более предпочтительный способ появился в языке позднее — это асинхронные функции (Async Functions), которые вызываются через async. В примере ниже функция my_coroutine задана асинхронно, то есть программа не будет ждать завершения ее работы, а продолжит выполнение следующих команд:
import asyncio # импортируем библиотеку async def my_async_function (seconds) : # создаем асинхронную функцию print ('Starting async function') await asyncio.sleep (seconds) # вызываем метод await для ожидания print ('Finishing async function') loop = asyncio.get_event_loop () # создаем объект loop.run_until_complete(my_async_function (2)) # запускаем loop.close () # закрываем
Кроме того, в Python можно создавать асинхронные контексты с помощью ключевого слова async with. Это позволяет выполнять асинхронные операции внутри контекста, например открытие и закрытие файла:
import asyncio # импортируем библиотеку async def read_file (filename): # создаем асинхронную функцию async with open(filename, 'r') as f: # открываем файл на чтение contents = await f. read () # читаем весь файл print (contents)
Модуль asyncio с методами async functions, async with, контексты и корутины — выбор средств асинхронности в Python неплохой. Комбинируя их, можно создавать программы с высокой параллельностью и улучшать их производительность, а также избегать блокировок программы во время длительных операций. Помните, что асинхронный код сам по себе более сложен для понимания и реализации, поэтому используйте его с умом. И тогда перечисленные инструменты раскроют весь свой немаленький потенциал.
Асинхронность во фреймворках Python — Django, FastAPI, Flask
Теперь поговорим об использовании асинхронности с популярными фреймворками — Django, Flask и FastAPI. Ни один из них не имеет встроенной поддержки асинхронности, но ее можно добавить с помощью внешних библиотек.
Для реализации асинхронных вызовов FastAPI использует стандартный модуль asyncio и поддерживает асинхронные функции нативно, на уровне ядра. У Django и Flask такой поддержки нет, но они тоже умеют работать с асинхронными библиотеками asyncio или aiohttp. Так что разогнать свои веб-приложения с помощью асинхронности использование этих фреймворков не помешает. Вот пример реализации с библиотекой aiohttp в Flask:
import aiohttp # импортируем библиотеку для работы с асинхронным примером from flask import Flask # импортируем библиотеку для работы с фреймворком app = Flask(__name__) # создаем приложение @app.route("/") # объявляем страницу async def main(): # создаем асинхронную функцию async with aiohttp.ClientSession() as session: # открываем асинхронную клиентскую сессию async with session.get ("https://www.example.com") as response: # используя сессию делаем асинхронный запрос return response.text if __name__ == Il “__main__”: # объявляем секцию main app.run() # запускаем фреймворк по с настройками по умолчанию
Асинхронность в веб-приложениях лучше всего раскрывается при работе с длительными операциями или вызовами API. Но учтите, что так вы подписываетесь на более сложную отладку и поддержку.
Вот еще пример асинхронных функций в FastAPI: функция main использует asyncio.sleep для задержки выполнения на 10 секунд. Это может пригодиться, например, для ожидания ответа от внешнего API:
from fastapi import FastAPI # импортируем библиотеку для работы с фреймворком Aimport asyncio # импортируем библиотеку для работы с асинхронным примером app = FastAPI() # создаем приложение @app.get("/") # объявляем страницу async def main(): #создаем асинхронную функцию await asyncio.sleep(10) # с помощью асинхронной библиотеки запускаем наш пример return if __name__ == "__main__": # объявляем секцию main uvicorn.run (app) # запускаем фреймворк по с настройками по умолчанию
Что касается Django, то он также поддерживает асинхронное программирование с помощью внешних библиотек Django Channels.
from channels.generic.websocket import AsyncWebsocketConsumer #библиотека для работы с асинхронностью §class MyConsumer (AsyncWebsocketConsumer): async def connect(self): # создаем асинхронный метод await self.accept() # ожидаем await asyncio.sleep (10) # выполняем действия await self.send(text_data="Hello World") # отправляем данные await self.close() # закрываем
В этом примере класс MyConsumer реализует асинхронное вебсокет-соединение через метод connect. Метод accept принимает соединение, а метод send отправляет сообщение клиенту. Для задержки отправки сообщения на 10 секунд используется функция asyncio.sleep. И в конце метод close закрывает соединение.
С помощью асинхронного программирования вы можете использовать все доступные ресурсы для обработки множества запросов одновременно, а не ставить их в очередь. Создаются асинхронные вьюхи в каждом фреймворке по-своему. В Django вы можете использовать декоратор async из библиотеки asyncio. Для Flask — декоратор asyncio.coroutine; Flask использует библиотеку gevent для управления асинхронными задачами. FastAPI имеет встроенную поддержку асинхронных функций, поэтому там можно использовать async def. Выбирайте фреймворк для работы с асинхронностью исходя из собственных задач и предпочтений. Я привел варианты выше, поскольку они точно предлагают удобный инструментарий для управления асинхронными задачами.
ORM — Object-Relational Mapping
ORM (Object-Relational Mapping) — это технология, которая позволяет связаться с базой данных, используя объекты Python, вместо того чтобы писать сырые SQL-запросы. Многие ORM для Python, такие как SQLAlchemy и Django ORM, поддерживают асинхронные версии. Библиотеки asyncio или asyncpg позволяют использовать асинхронные версии этих ORM в асинхронных приложениях.
С помощью ORM вы можете выполнять запросы к базе данных асинхронно, вместо того чтобы ждать ответа перед выполнением следующей задачи. Так вы можете увеличить производительность приложения и оптимизировать использование ресурсов. Пример асинхронного подключения к СУБД:
import asyncio # библиотека для работы с асинхронным кодом import asyncpg # библиотека для подключения к субд async def main(): ## создаем асинхронную функцию conn = await asyncpg.connect (user='user', password='password', database='database', host='host') # подключаем к субд # создание таблицы await conn.execute(''' CREATE TABLE IF NOT EXISTS test_table ( id serial PRIMARY KEY, name text NOT NULL ) ''') # вставка данных в таблицу await conn.execute('" INSERT INTO test_table (name) VALUES ($1) ''', 'John Doe') # выборка данных из таблицы result = await conn.fetch(''' SELECT * FROM test_table ''') print (result) # показываем результат await conn.close() # закрываем соединение asyncio.run(main())
В этом примере происходит соединение с базой данных, далее создание таблицы, вставка данных в таблицу и выборка данных. Все эти операции выполняются асинхронно, так что вы можете выполнять другие задачи одновременно с запросом к базе данных. Обработка запросов ускоряется и пользовательский опыт улучшается, так как во время ожидания ответа от базы данных приложение не проседает. Но еще раз напомню, что асинхронный код более сложен в реализации и отладке, поэтому оценивайте свои возможности и потребности проекта.
В нашей троице Django, Flask и FastAPI асинхронность в работе с базой данных можно реализовать через библиотеки asyncio и aiomysql. Они представляют собой асинхронные версии стандартных модулей для работы с базами данных, psycopg2 и mysql-python. Например в Django можно использовать asyncpg для работы PostgreSQL в асинхронном режиме. Соответственно, в Flask и FastAPI можно использовать aiomysql для MySQL.
Асинхронные ORM, такие как asyncio-orm или Tortoise-ORM, могут улучшить и производительность работы с базой данных в асинхронном режиме. В большинстве случаев асинхронный код позволяет использовать базу данных более эффективно за счет минимизации ожидания выполнения запросов. Покажу, как асинхронность может улучшить работу с базой данных, на примере с asyncio и aiomysql:
pip install aiomysql import asyncio # библиотека для работы с асинхронным кодом import aiomysql # библиотека для подключения к субд async def main(): # создаем асинхронную функцию conn = await aiomysql.connect(host='localhost', user='user', password='password', db='dbname', charset='utf8mb4') # подключаем к субд async with conn.cursor() as cursor: # открываем подключение await cursor.execute ("SELECT * FROM table") # добавляем запрос result = await cursor.fetchall() # получаем все из таблицы print(result) # показываем запрос asyncio.run(main ())
Здесь мы создали простое приложение, которое подключается к базе данных и выполняет запрос. Используется асинхронный контекст-менеджер для управления соединением с базой данных, а затем выполняется SELECT-запрос и вывод результата.
Использование асинхронности в ORM может повысить производительность приложения, поскольку запросы к базе данных при этом выполняются в фоновом режиме, без блокировки потоков исполнения. Но помните о неминуемом усложнении кода и отладки. Django ORM и некоторые другие ORM поддерживают асинхронные запросы. Запросы эти не встроены в фундаментальный дизайн фреймворка и могут требовать дополнительных инструментов и настроек. С этой точки зрения проще использовать Flask с его asyncio.
Ограничения асинхронности
Не все базы данных поддерживают асинхронный режим работы — например реляционные базы данных, такие как PostgreSQL и MySQL. При использовании таких баз данных с асинхронным кодом вам могут потребоваться специальные библиотеки типа asyncpg.
Еще одно ограничение возникает при работе с транзакциями. Они обычно выполняются в блокирующем режиме, который заставляет все остальные запросы ждать, пока транзакция не будет завершена. Это может стать проблемой в асинхронных приложениях, так как они ожидают ответа в неблокирующем режиме. Здесь есть несколько решений: использование асинхронных ORM (asyncpg) или использование блокировок на уровне базы данных. Однако так вы будете вынуждены потерять в производительности и писать более сложный код.
Все три фреймворка, что мы рассматривали выше — FastAPI, Django и Flask — используют ORM (Object Relational Mapping) для управления базами данных. В ORM для работы с базами данных предусмотрены простые CRUD-операции (Create, Read, Update, Delete). В FastAPI и Flask ORM реализуют через сторонние библиотеки, такие как SQLAlchemy и Flask-SQLAlchemy. После этого с базами данных можно использовать и синхронные, и асинхронные операции (async for, async with, async/await). Django же с версии 3.0 поддерживает асинхронные операции с базой данных нативно, и вам тоже не придется ждать.
Заключение
Сегодня асинхронность очень важна для решения проблем с производительностью в веб-приложениях. В Python асинхронные функции можно организовать с помощью модуля asyncio. В фреймворках Django, Flask и FastAPI можно использовать асинхронные возможности для оптимизации работы с базами данных и выполнения сложных операций.
Следует помнить, что асинхронный стиль программирования усложнит код и отладку. И, конечно, потребует довольно глубокого понимания асинхронных принципов. Так что решение об использовании асинхронности должно быть осознанным и основываться на конкретных задачах.
Несмотря на это, асинхронность остается важным инструментом для улучшения производительности веб-приложений.
Смешивание асинхронного и синхронного кода в Python
Допустим, есть приложение на flask + socketio + eventlet. Внутри обработчика сообщения от socketio я могу писать какой-нибудь синхронный код. Например, сделать print или отправить ответ клиенту. Для конкретики вот примерный мой код:
import eventlet import eventlet.wsgi import socketio from flask import Flask, render_template sio = socketio.Server() app = Flask(__name__) @app.route('/') def main(): return render_template('main.html') @sio.on('my-msg') def handle_login(sid, data): print('my-msg: ' + str(data)) if __name__ == '__main__': app = socketio.Middleware(sio, app) eventlet.wsgi.server(eventlet.listen(('', 8000)), app)
Однако, мне нужно работать с библиотекой, которая поддерживает только асинхронный стиль программирования. Не на базе eventlet или чего-то подобного, а на базе непосредственно yield from и т. п. Каким образом я могу делать к ней обращения внутри обработчика сообщения?
Пока приходит в голову, что нужно запустить в отдельном потоке eventloop от asyncio и запускать coroutine в нём при приходе сообщения. В свою очередь по окончании работы coroutine нужно как-то вызвать sio.emit (но это может быть не безопасно из-за того, что я делаю это из другого потока).
KivApple ★★★★★
18.11.16 15:28:20 MSK

Обычно есть синхронные helper-ы. Например, для tornado есть run_sync
Для asyncio, вроде как (сам с asyncio не работал), должно работать run_until_complete
Vovka-Korovka ★★★★★
( 18.11.16 16:13:02 MSK )
Последнее исправление: Vovka-Korovka 18.11.16 16:13:25 MSK (всего исправлений: 1)
Ответ на: комментарий от Vovka-Korovka 18.11.16 16:13:02 MSK

Во, даже пример для asyncio есть
Vovka-Korovka ★★★★★
( 18.11.16 16:14:28 MSK )
Ответ на: комментарий от Vovka-Korovka 18.11.16 16:14:28 MSK
У меня немного другой случай. eventlet тоже не совсем синхронный — он event-driven, насколько я понимаю. То есть там главный цикл ждёт всяких событий и вызывает нужные обработчики. Если я подвешу обработчик события, то другие события не будут обрабатываться. А это плохо.
Мне нужно как-то запустить асинхронный код, при этом чтобы он не остановил выполнение eventlet. А когда асинхронный код выполнится, мне необходимо сделать sio.emit(. ).
По факту и то, и то — асинхронное программирование, но реализованное по-разному (asyncio позволят писать типа синхронно, но на самом деле асинхронно, eventlet заставляет самостоятельно делать машину состояний).
KivApple ★★★★★
( 18.11.16 16:22:52 MSK ) автор топика
Ответ на: комментарий от KivApple 18.11.16 16:22:52 MSK

Ну тогда вариантов два
1. Наиболее правильный — искать/писать переходники между разными event-loop-ами. 2. Второй вариант — то, что ты описал. Запускать в отдельном потоке.
Vovka-Korovka ★★★★★
( 18.11.16 16:30:17 MSK )

Я как всегда не въехал в суть проблемы, но ты можешь использовать разные потоки и очереди.
Только вот надо понять какая очередь тебе подойдёт. Если ты передаёшь из асинхронного кода в синхронный то queue.Queue. Если наоборот. то хз, asyncio.Queue не подойдёт, тебе нужен анус (янус?): http://stackoverflow.com/questions/32889527/is-there-a-way-to-use-asyncio-que. . Либо call_soon_threadsafe(), но я им пока ещё не пользовался.
true_admin ★★★★★
( 18.11.16 16:43:55 MSK )
Ответ на: комментарий от true_admin 18.11.16 16:43:55 MSK
Вот я сейчас как раз попытался вызвать call_soon_threadsafe:
from datetime import timedelta import eventlet import eventlet.wsgi import socketio import asyncio from threading import Thread from flask import Flask, render_template sio = socketio.Server() app = Flask(__name__) loop = asyncio.new_event_loop() @app.route('/') def main(): return render_template('main.html') @sio.on('my-msg') def handle_my_msg(sid, data): loop.call_soon_threadsafe(handle_my_msg_async, (data,)) @asyncio.coroutine def handle_my_msg_async(data): print(str(data)) def run_loop(loop): asyncio.set_event_loop(loop) loop.run_forever() if __name__ == '__main__': loop_thread = Thread(target=run_loop, args=(loop,)) loop_thread.start() app = socketio.Middleware(sio, app) eventlet.wsgi.server(eventlet.listen(('', 8000)), app)
В результате получаю ошибку:
TypeError: coroutines cannot be used with call_soon()
За идею с очередью спасибо. Думаю, её стоит использовать для передачи данных обратно. В смысле, что мне нужно как-то вызвать sio.emit, чтобы отдать ответ клиенту и скорее всего это можно сделать только из цикла eventlet.
KivApple ★★★★★
( 18.11.16 16:48:27 MSK ) автор топика
Последнее исправление: KivApple 18.11.16 16:49:19 MSK (всего исправлений: 1)
Ответ на: комментарий от KivApple 18.11.16 16:48:27 MSK

Я тебе 100% правильного ответа не дам т.к. давно уже с asyncio не баловался. Попробуй убрать декоратор asyncio.coroutine.
true_admin ★★★★★
( 18.11.16 17:15:08 MSK )
Ответ на: комментарий от true_admin 18.11.16 17:15:08 MSK
Написал на его основе небольшой модуль:
from threading import Thread, current_thread, Event import asyncio import functools from concurrent.futures import Future class AsyncThread(Thread): def __init__(self, start_event=Event()): Thread.__init__(self) self.loop = None self.tid = None self.event = start_event def run(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.tid = current_thread() self.loop.call_soon(self.event.set) self.loop.run_forever() def stop(self): self.loop.call_soon_threadsafe(self.loop.stop) def add_task(self, coro): """this method should return a task object, that I can cancel, not a handle""" def _async_add(func, fut): try: ret = func() fut.set_result(ret) except Exception as e: fut.set_exception(e) f = functools.partial(asyncio.async, coro, loop=self.loop) if current_thread() == self.tid: return f() # We can call directly if we're not going between threads. else: # We're in a non-event loop thread so we use a Future # to get the task from the event loop thread once # it's ready. fut = Future() self.loop.call_soon_threadsafe(_async_add, f, fut) return fut.result() def cancel_task(self, task): self.loop.call_soon_threadsafe(task.cancel) def wait(self): self.event.wait()
Теперь можно делать так:
async_thread = AsyncThread() async_thread.start() async_thread.wait() . @sio.on('my-msg') def handle_my_msg(sid, data): async_thread.add_task(handle_my_msg_async(data)) @asyncio.coroutine def handle_my_msg_async(data): print(str(data))
KivApple ★★★★★
( 18.11.16 17:20:22 MSK ) автор топика
Ответ на: комментарий от KivApple 18.11.16 17:20:22 MSK

Да, оно, по-сути, создаёт таск, поэтому работает. Сам по себе короутин/генератор не может исполняться напрямую в event loop, его нужно обернуть в task или future.
Я бы попробовал тупо вызвать create_task() на короутин и скормить его call_soon_threadsafe . Тот код что ты показал хорош, но как-то слишком наворочено, ведь твою проблему можно решить в одну строчку. Ну, это тебе решать.
true_admin ★★★★★
( 18.11.16 17:25:30 MSK )
Ответ на: комментарий от KivApple 18.11.16 17:20:22 MSK

А может я и нагнал про create_task. Asyncio работает слишком мудрёно для меня, я без доков и экспериментов не скажу будет это работать или нет.
true_admin ★★★★★
( 18.11.16 17:39:48 MSK )
Ответ на: комментарий от true_admin 18.11.16 17:25:30 MSK
Теперь главная проблема как вызвать sio.emit. Если я это делаю прямо из асинхронного кода, то ничего клиенту не приходит. Если делаю прямо из обработчика события socketio, то приходит.
То есть по сути дела мне нужно действие аналогичное call_soon_threadsafe, но для eventlet.
KivApple ★★★★★
( 18.11.16 17:56:33 MSK ) автор топика
Последнее исправление: KivApple 18.11.16 18:05:51 MSK (всего исправлений: 1)
Ответ на: комментарий от KivApple 18.11.16 17:56:33 MSK

Я не знаю что такое eventlet и прочее, зачем оно тебе вообще нужно? Если для http и вебсокетов то просто юзай aiohttp.
true_admin ★★★★★
( 18.11.16 18:13:49 MSK )
Ответ на: комментарий от true_admin 18.11.16 18:13:49 MSK
Flask вроде как не умеет его использовать. Только один из более старых event loop’ов.
KivApple ★★★★★
( 18.11.16 18:31:01 MSK ) автор топика
Ответ на: комментарий от KivApple 18.11.16 18:31:01 MSK

Так я про то что flask может быть вообще не нужен :). aiohttp поддерживает вебсокеты, сессии, авторизацию сам прикрутишь :). Шаблоны рендерить тоже не проблема. Нужен ли тебе фласк вообще?
true_admin ★★★★★
( 18.11.16 19:18:31 MSK )
Ответ на: комментарий от true_admin 18.11.16 19:18:31 MSK
Уже так подумал и выпилил flask. Для вебсокетов использую sockjs вместо socket.io (всё же по сравнению с обычными вебсокетам мне нравится, что в случае проблем клиент перейдёт на более старые технологии).
Только вот не могу понять, можно ли заставить здешний роутер на все непонятные запросы (по факту всё, что не начинается на /static/) отдавать /static/index.html (там одностраничное приложение, которое использует History API).
KivApple ★★★★★
( 18.11.16 19:50:35 MSK ) автор топика
Последнее исправление: KivApple 18.11.16 19:52:28 MSK (всего исправлений: 3)
Ответ на: комментарий от KivApple 18.11.16 19:50:35 MSK

Может, там есть дефолтный роутер или можно тупо перехватить 404?
Ошибка при установке eventlet на Python
Возникла необходимость установить библиотеку eventlet. Сначала вылетала ошибка при установке через pip, где нужно было установить VS C++ BuildTools. Устранил ее, но появилась новая.
Requirement already satisfied: eventlet in c:\users\user\global\flask_app\venv\lib\site-packages\eventlet-0.25.1-py3.8.egg (0.25.1) Requirement already satisfied: dnspython>=1.15.0 in c:\users\user\global\flask_app\venv\lib\site-packages (from eventlet) (1.16.0) Collecting greenlet>=0.3 Using cached greenlet-0.4.15.tar.gz (59 kB) Requirement already satisfied: monotonic>=1.4 in c:\users\user\global\flask_app\venv\lib\site-packages (from eventlet) (1.5) Requirement already satisfied: six>=1.10.0 in c:\users\user\global\flask_app\venv\lib\site-packages (from eventlet) (1.14.0) Building wheels for collected packages: greenlet Building wheel for greenlet (setup.py) . error ERROR: Command errored out with exit status 1: command: 'c:\users\user\global\flask_app\venv\scripts\python.exe' -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\User\\AppData\\Local\\Temp\\pip-install-ely6dpqt\\greenlet\\setup.py'"'"'; __file__='"'"'C:\\Users\\User\\AppData\\Local\\Temp\\ pip-install-ely6dpqt\\greenlet\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d 'C:\Users\User\AppData\Local\Temp\pip-wheel-5q 3fw3yi' cwd: C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\ Complete output (51 lines): running bdist_wheel running build running build_ext building 'greenlet' extension Traceback (most recent call last): File "", line 1, in File "C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\setup.py", line 71, in setup( File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\__init__.py", line 145, in setup return distutils.core.setup(**attrs) File "c:\program files (x86)\python38-32\Lib\distutils\core.py", line 148, in setup dist.run_commands() File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 966, in run_commands self.run_command(cmd) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\users\user\global\flask_app\venv\lib\site-packages\wheel\bdist_wheel.py", line 223, in run self.run_command('build') File "c:\program files (x86)\python38-32\Lib\distutils\cmd.py", line 313, in run_command self.distribution.run_command(command) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\program files (x86)\python38-32\Lib\distutils\command\build.py", line 135, in run self.run_command(cmd_name) File "c:\program files (x86)\python38-32\Lib\distutils\cmd.py", line 313, in run_command self.distribution.run_command(command) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 340, in run self.build_extensions() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 449, in build_extensions self._build_extensions_serial() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 474, in _build_extensions_serial self.build_extension(ext) File "C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\my_build_ext.py", line 42, in build_extension _build_ext.build_extension(self, ext) File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 528, in build_extension objects = self.compiler.compile(sources, File "c:\program files (x86)\python38-32\Lib\distutils\_msvccompiler.py", line 360, in compile self.initialize() File "c:\program files (x86)\python38-32\Lib\distutils\_msvccompiler.py", line 253, in initialize vc_env = _get_vc_env(plat_spec) File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 171, in msvc14_get_vc_env return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 1592, in return_env self.UCRTIncludes, File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 1508, in UCRTIncludes include = join(self.si.UniversalCRTSdkDir, 'include') File "c:\users\user\global\flask_app\venv\lib\ntpath.py", line 78, in join path = os.fspath(path) TypeError: expected str, bytes or os.PathLike object, not NoneType ---------------------------------------- ERROR: Failed building wheel for greenlet Running setup.py clean for greenlet Failed to build greenlet Installing collected packages: greenlet Running setup.py install for greenlet . error ERROR: Command errored out with exit status 1: command: 'c:\users\user\global\flask_app\venv\scripts\python.exe' -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\User\\AppData\\Local\\Temp\\pip-install-ely6dpqt\\greenlet\\setup.py'"'"'; __file__='"'"'C:\\Users\\User\\AppData\\Local\\Temp \\pip-install-ely6dpqt\\greenlet\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\User\AppData\Local\Temp\pip-reco rd-dqboxgu8\install-record.txt' --single-version-externally-managed --compile --install-headers 'c:\users\user\global\flask_app\venv\include\site\python3.8\greenlet' cwd: C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\ Complete output (53 lines): running install running build running build_ext building 'greenlet' extension Traceback (most recent call last): File "", line 1, in File "C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\setup.py", line 71, in setup( File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\__init__.py", line 145, in setup return distutils.core.setup(**attrs) File "c:\program files (x86)\python38-32\Lib\distutils\core.py", line 148, in setup dist.run_commands() File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 966, in run_commands self.run_command(cmd) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\command\install.py", line 61, in run return orig.install.run(self) File "c:\program files (x86)\python38-32\Lib\distutils\command\install.py", line 545, in run self.run_command('build') File "c:\program files (x86)\python38-32\Lib\distutils\cmd.py", line 313, in run_command self.distribution.run_command(command) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\program files (x86)\python38-32\Lib\distutils\command\build.py", line 135, in run self.run_command(cmd_name) File "c:\program files (x86)\python38-32\Lib\distutils\cmd.py", line 313, in run_command self.distribution.run_command(command) File "c:\program files (x86)\python38-32\Lib\distutils\dist.py", line 985, in run_command cmd_obj.run() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 340, in run self.build_extensions() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 449, in build_extensions self._build_extensions_serial() File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 474, in _build_extensions_serial self.build_extension(ext) File "C:\Users\User\AppData\Local\Temp\pip-install-ely6dpqt\greenlet\my_build_ext.py", line 42, in build_extension _build_ext.build_extension(self, ext) File "c:\program files (x86)\python38-32\Lib\distutils\command\build_ext.py", line 528, in build_extension objects = self.compiler.compile(sources, File "c:\program files (x86)\python38-32\Lib\distutils\_msvccompiler.py", line 360, in compile self.initialize() File "c:\program files (x86)\python38-32\Lib\distutils\_msvccompiler.py", line 253, in initialize vc_env = _get_vc_env(plat_spec) File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 171, in msvc14_get_vc_env return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 1592, in return_env self.UCRTIncludes, File "c:\users\user\global\flask_app\venv\lib\site-packages\setuptools\msvc.py", line 1508, in UCRTIncludes include = join(self.si.UniversalCRTSdkDir, 'include') File "c:\users\user\global\flask_app\venv\lib\ntpath.py", line 78, in join path = os.fspath(path) TypeError: expected str, bytes or os.PathLike object, not NoneType ---------------------------------------- ERROR: Command errored out with exit status 1: 'c:\users\user\global\flask_app\venv\scripts\python.exe' -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\User\\AppData\\Local\\Temp\\pip-install-ely6dpqt\\greenlet\\setup.py'"'"'; __file__='"'"'C:\\ Users\\User\\AppData\\Local\\Temp\\pip-install-ely6dpqt\\greenlet\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users \User\AppData\Local\Temp\pip-record-dqboxgu8\install-record.txt' --single-version-externally-managed --compile --install-headers 'c:\users\user\global\flask_app\venv\include\site\python3.8\greenlet' Check the logs for full command output.
P.S.: устанавливал тремя способами — через pip, easy_installer и просто пытался выполнить setup.py скачанного заранее с гита пакета.
Отслеживать
задан 3 фев 2020 в 12:37
Brain of Мadness Brain of Мadness
304 2 2 серебряных знака 14 14 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
В общем, в ответах, которые нашел в гугле, кто-то дал ссылку на битый VS C++ Build Tools. Нашел нормальный и все удалось установить. Ссылку прилагаю — https://go.microsoft.com/fwlink/?LinkId=691126
Отслеживать
ответ дан 3 фев 2020 в 15:21
Brain of Мadness Brain of Мadness
304 2 2 серебряных знака 14 14 бронзовых знаков
Вообще этот компонент подойдет всем тем, кто сталкивался при установке библиотек с ошибкой отсутствия как раз таки VS C++ Build Tools 14.