Если вы заметили значительное ускорение при использовании PyPy вместо CPython, это означает, что ваш код, вероятно, не связан с I / O. Это означает, что асинхронный ввод-вывод не очень поможет. Кроме того, это также будет дополнительной работой, потому что вам придется реструктурировать все ваши загруженные ЦП задачи на маленькие куски, которые могут повторяться await
, чтобы они не блокировали другие задачи.
Итак, вы, вероятно, хотите использовать несколько процессов здесь.
Самое простое решение - использовать concurrent.futures.ProcessPoolExecutor
: просто бросить задачи исполнителю, и он запустит их на дочерних процессах и вернет вам Future
.
В отличие от asyncio
, вам не придется менять эти задачи вообще. Они могут читать файл, просто зацикливаясь на модуле csv
, обрабатывая все это в одном большом блоке, и даже использовать синхронный модуль ftplib
, не беспокоясь о том, что кто-то блокирует кого-то еще. Только ваш код верхнего уровня должен быть изменен.
Однако вы можете рассмотреть возможность разделения кода на wx
GUI, который вы запускаете в CPython, и на многопроцессорный движок, который вы запускаете через subprocess
в PyPy, который затем выделяет ProcessPoolExecutor
в PyPy как Что ж. Это заняло бы немного больше работы, но это означает, что вы получите преимущества от использования PyPy для ЦП, хорошо проверенные преимущества с использованием CPython и параллелизм многопроцессорной обработки.
Другой вариант, который следует рассмотреть, - это использовать библиотеку, такую как NumPy или Pandas, которая может выполнять медленные части (будь то чтение и обработка CSV, или выполнение каких-либо поэлементных вычислений для тысяч строк или что-то еще) быстрее (и возможно, даже выпуская GIL, что означает, что вам не нужна многопроцессорная обработка.
Если ваш код на самом деле является кодом, связанным с вводом / выводом и в первую очередь связанным с запросами FTP, asyncio
поможет. Но это потребует переписывания большого количества кода. Вам нужно будет найти или написать клиентскую библиотеку FTP с поддержкой asyncio
. И, если чтение файла занимает значительную часть вашего времени, преобразование этого в асинхронное будет еще более трудоемким.
Существует также проблема интеграции цикла событий wx
с циклом событий asyncio
. Возможно, вам удастся избежать выполнения цикла asyncio
во втором потоке, но тогда вам нужно будет найти какой-то способ связи между циклом событий wx
в основном потоке и циклом asyncio
в фоновый поток. В качестве альтернативы, вы можете использовать один цикл для другого (или даже сторонние библиотеки, которые делают это за вас). Но это может быть намного проще сделать (или иметь более подходящие сторонние библиотеки), например, twisted
вместо asyncio
.
Но, если вам не нужен массовый параллелизм (чего, вероятно, нет, если у вас нет сотен различных FTP-серверов для общения), потоки должны работать так же хорошо, с гораздо меньшими изменениями в вашем коде. Просто используйте concurrent.futures.ThreadPoolExecutor
, что почти идентично использованию ProcessPoolExecutor
, как описано выше.