为什么在子进程中调用fuser会返回多个PID?

时间:2015-03-24 22:19:25

标签: python unix subprocess fuser

我有以下文件(用于py.test编写):

# test_fuser.py
import subprocess


def fuser(filename):
    return subprocess.check_output(['fuser', filename]).split()


def test_fuser_0(tmpdir):
    test_file = tmpdir.join('test.txt')
    test_file.write('')
    assert len(fuser(test_file.strpath)) == 0


def test_fuser_1(tmpdir):
    test_file = tmpdir.join('test.txt')
    test_file.write('')
    with open(test_file.strpath, 'w'):
        assert len(fuser(test_file.strpath)) == 1

从命令行运行py.test会产生:

$ py.test test_fuser.py
================================= test session starts ==================================
platform darwin -- Python 2.7.8 -- py-1.4.26 -- pytest-2.6.4
collected 2 items

test_fuser.py .F

======================================= FAILURES =======================================
_____________________________________ test_fuser_1 _____________________________________

tmpdir = local('/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-131/test_fuser_10')

    def test_fuser_1(tmpdir):
        test_file = tmpdir.join('test.txt')
        test_file.write('')
        with open(test_file.strpath, 'w'):
>           assert len(fuser(test_file.strpath)) == 1
E           assert 2 == 1
E            +  where 2 = len(['71433', '71437'])
E            +    where ['71433', '71437'] = fuser('/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-131/test_fuser_10/test.txt')
E            +      where '/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-131/test_fuser_10/test.txt' = local('/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-131/test_fuser_10/test.txt').strpath

test_fuser.py:18: AssertionError
--------------------------------- Captured stderr call ---------------------------------
/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-131/test_fuser_10/test.txt:
========================= 1 failed, 1 passed in 10.32 seconds =========================

这是不寻常的,因为人们会期望fuser()返回一个PID,而不是两个,因为只有对open()的调用才能打开文件。

为了进一步调查,我在调用test_fuser_1()之前fuser()设置了一个断点,在open()的上下文中,然后重新进行测试。

def test_fuser_1(tmpdir):
    test_file = tmpdir.join('test.txt')
    test_file.write('')
    with open(test_file.strpath, 'w'):
        pytest.set_trace()
        assert len(fuser(test_file.strpath)) == 1

在断点处,我抓住了临时文件的名称:

>>>>>>>>>>>>>>>>>>>>>>> PDB set_trace (IO-capturing turned off) >>>>>>>>>>>>>>>>>>>>>>>>
> /Users/caesarbautista/Desktop/test_fuser.py(21)test_fuser_1()
-> assert len(fuser(test_file.strpath)) == 1
(Pdb) test_file.strpath
'/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-132/test_fuser_10/test.txt'

然后,从另一个终端呼叫fuser我看到了一个PID。

$ fuser /private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-132/test_fuser_10/test.txt
/private/var/folders/mx/h4mybl9x1p52wbj2hnvk1lgh0000gn/T/pytest-132/test_fuser_10/test.txt: 71516

这似乎表明子流程负责第二个PID,但我不确定为什么会这样,并且已经没有关于如何进一步调查这个问题的想法。知道第二个PID的来源吗?

我虽然也许py.test可能与此相关,所以我重写了测试用于鼻子:

def test_fuser_0():
    with open('test.txt', 'w') as fp:
        fp.write('')
    pids = fuser('test.txt')
    assert len(pids) == 0, pids


def test_fuser_1():
    with open('test.txt', 'w') as fp:
        fp.write('')
        pids = fuser('test.txt')
        assert len(pids) == 1, pids

但是用鼻子跑它们会导致同样的失败:

$ nosetests --tests=test_fuser.py
test.txt:
.test.txt:
F
======================================================================
FAIL: test_fuser.test_fuser_1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/opt/boxen/homebrew/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/caesarbautista/Desktop/test_fuser.py", line 34, in test_fuser_1
    assert len(pids) == 1, pids
AssertionError: ['71865', '71869']

----------------------------------------------------------------------
Ran 2 tests in 11.026s

FAILED (failures=1

0 个答案:

没有答案