Павел Соколов, А вот если моды, то там оператор import уже неудобен.
importlib в руки, делаем список имён модулей для импорта (да хоть список py-файлов в нужном каталоге), импортируем по одному через importlib.import_module(), складываем, скажем, в словарь {имя: объект модуля}, и дальше через этот словарь уже с модулями работаем.
Поспорю с вами. Например, коллекция в цикле foreach сигнализирует о своём завершении исключением StopIteration.
А отлов KeyError при чтении из словаря примерно так же быстр, как и другие методы.
Так что исключения в питоне вполне применимы. Да, бросать их не по делу не стоит, но если без фанатизма... мне кажется, в такой ситуации это оправданно. Сравните с asyncio.CancelledError.
В if вообще заходит? Правильный ли путь генерируется?
cwd - это не путь к скрипту, это текущий каталог (может совпадать, может отличаться).
Если нужен путь к скрипту, sys.argv[0] в помощь.
К слову, соединять пути лучше через os.path.join()
Во-первых, имеет смысл выделить команды в отдельный тип события, и парсить их из сообщений в одном месте, а не в каждом обработчике.
Во-вторых, смотря какого плана нагрузка на бота.
Если команды CPU-bound, т.е. что-то активно считают, но делают не так много ввода-вывода, то делать пул потоков или процессов (через multiprocessing), и прогонять обработчики через них.
Если команды IO-bound, т.е. в основном делают ввод вывод (http запросы, работу с диском, с базой и пр), то тогда проектировать бота асинхронным, и выполнять обработчики не один за одним, а вместе через asyncio.gather(). Не придётся париться с многопоточностью, но зато пока одна команда ждёт ввода/вывода - другие работают.
И да, 20к запросов в секунду - это очень много. Тут уже нужно как-то шардировать бота, т.е. запускать неколько ботов под одной учёткой, и работающих с одной базой.
Я бы взялся за C++, так как он сравнительно легко позволяет обращаться к таким вещам. Сделал бы proof of concept, а потом при надобности портировал на другой язык. Но я плюсы уже худо-бедно знаю. Если не знать, то будет сложнее, а не проще.
В принципе можно также добиться результата и на C#, но как и питон, шарп далёк от таких вещей (хотя достучаться можно).
Так что если существующих знаний мало - то стоит попытаться на том языке, который знаете. Модуль я вам подсказал.
Последовательность у вас будет, скорее всего, CreateProcess() для запуска процесса (нужно узнать дескриптор и ID запущенного процесса), потом ReadProcessMemory() (возможно, в цикле), и при необходимости использовать приём с DebugActiveProcess() чтобы приостановить целевой процесс.
Алексей Фобиус, в смысле асинхронно?
А контуры - орагнизуй цикл по контурам, скинь в отдельный список те, которые удовлетворяют твоим условиям, потом рисуй только их через cv2.polylines(), к примеру.
Что значит "перекидывается"?
Дискорд не позволяет перемещать сообщения между каналами, насколько я знаю.
Максимум, бот может написать то же самое сообщение в другом канале (от своего имени!), и удалить оригинал.