subprocess.Popen不是线程安全的?

时间:2012-02-18 01:32:40

标签: python thread-safety subprocess popen

我根据a Python issue - closed/fixed编写了这个小测试类,它似乎发生在Fedora 15上的Python 2.7.1中。

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”。但是,有时它显示“正在运行”或“正在运行\ n \ n运行”。

(删除了对实际问题的引用,因为这是一个虚假的症状,感谢@ phihag的回答)。

实际问题:https://stackoverflow.com/questions/9338409/python-subprocess-popen-corrupts-binary-streams

1 个答案:

答案 0 :(得分:2)

您所看到的行为与子流程无关;我可以用:

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

这是因为Python's print is not thread-safe。为了避免打印文本和换行符之间的竞争条件,直接写入stdout,如下所示:

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

这假设对stdout的基础write调用是线程安全的。 That depends on the platform