Я понимаю, что потоки в Python используют один и тот же экземпляр интерпретатора Python. Мой вопрос - это то же самое с процессом, созданным os.fork
? Или каждый процесс, созданный os.fork
, имеет свой собственный интерпретатор?
Использует ли python os.fork тот же интерпретатор python?
Ответ 1
Всякий раз, когда вы используете fork, весь процесс Python дублируется в памяти (включая интерпретатор Python, ваш код и любые библиотеки, текущий стек и т.д.), чтобы создать второй процесс - одна из причин, по которой обработка процесса намного дороже, чем создание поток.
Это создает новую копию интерпретатора python.
Одним из преимуществ использования двух интерпретаторов python является то, что теперь у вас есть два GIL (Global Interpreter Locks) и, следовательно, может иметь истинную многопроцессорную обработку в многоядерной системе.
В потоках одного процесса используется один и тот же GIL, что означает, что только один выполняется в данный момент, давая только иллюзию parallelism.
Ответ 2
В то время как fork
действительно создает копию текущего интерпретатора Python, а не работает с одним и тем же, обычно это не то, что вы хотите, по крайней мере, не самостоятельно. Среди других проблем:
- На некоторых платформах могут возникать проблемы с многопоточными процессами. И некоторые библиотеки (наиболее известные Apple Cocoa/CoreFoundation) могут запускать потоки для вас в фоновом режиме или использовать поточно-локальные API, даже если у вас есть только один поток и т.д., Без вашего ведома.
- В некоторых библиотеках предполагается, что каждый процесс будет инициализирован правильно, но если вы
fork
после инициализации, это не так. Самое печально, если вы позволитеssl
засеять его PRNG в основном процессе, тогда fork у вас теперь есть потенциально предсказуемые случайные числа, что является большой дырой в вашей безопасности. - Открытые дескрипторы файлов наследуются (как дубликаты) детьми, с деталями, которые различаются раздражающими способами между платформами.
- POSIX требует только платформы для реализации очень специфического набора системных вызовов между
fork
иexec
. Если вы никогда не звонитеexec
, вы можете использовать только эти системные вызовы. Что в основном означает, что вы не можете сделать ничего портативно. - Все, что связано с сигналами, особенно раздражает и не переносится после
fork
.
Подробнее об этих проблемах см. POSIX fork
или на странице руководства по платформе.
Правильный ответ почти всегда заключается в использовании multiprocessing
или concurrent.futures
(который обертывает up multiprocessing
) или аналогичную стороннюю библиотеку.
С 3.4+ вы даже можете указать метод запуска. Метод fork
в основном просто вызывает fork
. Метод forkserver
запускает один "чистый" процесс (без потоков, обработчиков сигналов, инициализации SSL и т.д.) И отбрасывает у них новых детей. Метод spawn
вызывает fork
, затем exec
, или эквивалент, такой как posix_spawn
, чтобы получить вам новый интерпретатор вместо копии. Таким образом, вы можете начать с fork
, ut, а затем, если возникнут какие-либо проблемы, переключитесь на forkserver
или spawn
, и ничего больше в вашем коде не изменится. Что довольно приятно.
Ответ 3
os.fork()
эквивалентен syscall fork()
во многих UNIC (es). Итак, да ваш подпроцесс будет отделен от родителя и иметь другой интерпретатор (как таковой).
ВИЛКИ (2)
NAME fork - создать дочерний процесс
СИНТАКСИС #include
pid_t fork(void);
ОПИСАНИЕ fork() создает новый процесс путем дублирования вызывающего процесса. Новый процесс, называемый ребенком, является точной копией вызывающего процесса, называемой родительским, за исключением следующих точек:
os.fork()
Выполните дочерний процесс. Верните 0 в ребенка и id дочернего процесса в родительском элементе. Если возникает ошибка OSError поднят.Обратите внимание, что некоторые платформы, включая FreeBSD <= 6.3, Cygwin и OS/2 EMX имеют известные проблемы при использовании fork() из потока.
Смотрите также: Мартин Конечный ответ о том, почему и преимущества "разветвления":)
Для краткости; другие подходы к concurrency, которые не связаны с отдельным процессом, поэтому отдельный интерпретатор Python включает в себя:
- Зеленые или легкие потоки; ala greenlet
- Генераторы Coroutines ala Python и новый Python 3+
yield from
- Async I/O ala asyncio, Twisted, circuits и т.д.