subprocess.Popen не потокобезопасный? - PullRequest
2 голосов
/ 18 февраля 2012

Я написал этот небольшой тестовый класс, основанный на проблеме с Python - закрыт / исправлен , и, похоже, она возникает в Python 2.7.1 на Fedora 15.

from subprocess import Popen, PIPE
from threading import Thread

OUTPUT = "asl;dkfhqwiouethnjzxvnhsldfhuyasdhofuiweqamchuisemfawepfhuaipwemhfuaehfclkuehnflw ehfcoiuwehfiuwmhefuiwehfoiuhSfcl hfulh fuiqhuif huiwafh uiahf iUH fhh flkJH fl HASLFuhSAIULFhSUA HFulSAHfOI SUFChiuwqhncriouweycriuowanbyoUIWCryu iWyruawyrouiWYRcoiu YCRoiuNr uyr oUIAWryocIUWRNyc owuroiuNr cuWyrnawueitcnoy U IuiR yiuowaYnorc oWIUAr coiury iuoAW rnuoi asdfsdfd\n"


class X(Thread):
    def __init__(self):
        Thread.__init__(self)

    def run(self):
        print("Running")
        for i in xrange(10):
            s = Popen(
                "cat /tmp/junk",
                shell=True,
                stdout=PIPE,
                universal_newlines=True
            )
            output = s.communicate()[0]
            if not output == OUTPUT:
                print("Error: %r" % output)


XThreads = set([])

for i in xrange(1000):
    XThreads.add(X())

for x in XThreads:
    x.start()

Просто создайте файл, / tmp / junk в этом случае, который содержит OUTPUT, за исключением последнего символа новой строки.

Запустив это, вы ожидаете увидеть «Running» в каждой строке. Однако иногда отображается «Running» или «RunningRunning \ n \ nRunning».

(Удалено цитирование к реальной проблеме, поскольку это был ложный симптом, благодаря ответу @ phihag).

Актуальный выпуск: https://stackoverflow.com/questions/9338409/python-subprocess-popen-corrupts-binary-streams

1 Ответ

2 голосов
/ 18 февраля 2012

Поведение, которое вы видите, не имеет ничего общего с подпроцессом; Я могу воспроизвести это с:

import threading
def run(): print("Running")
for x in [threading.Thread(target=run) for i in range(1000)]:
    x.start()

Это потому, что Python's print не является поточно-ориентированным . Чтобы избежать расхождения между распечаткой текста и новой строкой, напишите напрямую в стандартный вывод, например:

import threading,sys
def run(): sys.stdout.write("Running\n")
for x in [threading.Thread(target=run) for i in range(1000)]:
    x.start()

Предполагается, что базовые write вызовы stdout являются поточно-ориентированными. Это зависит от платформы .

...