子流程中断管道和文件繁忙



我正在尝试使用python做一些文件系统方面的工作,因为我不想处理复杂的shell脚本,而是尽可能地将所有编程限制在python上。"search_string"中的shell命令读取目录中的文件名,并将前10个名称写入文件中。

search_string = "find " + rootDir + "/"+str(k)  +" -iname "*" -type f | head -10  >> negatives" + str(i) + ".txt"
print(search_string)
subprocess.call(search_string, shell=True)

这段代码适用于我的ubuntu 14.04 pc,但不适用于aws,这是最终必须运行的地方,给出了错误:

find: `standard output': Broken pipe
find: write error
ubuntu@ip:$ uname -r
3.13.0-37-generic

因此,我决定将长shell命令写入一个我认为很容易调用的文件(在使用chmod命令使shell脚本文件可执行之后):

search_string = "sudo find " + rootDir + "/"+str(k)  +" -iname "*" -type f | head -10  >> trainingfiles/negatives" + str(i) + ".txt"
f=open("cmd.sh","w")
f.write(search_string)
f.flush()
os.fsync(f.fileno())
f.close
p1=subprocess.Popen(["chmod","+x","/home/www-data/web2py/applications/fingerPrint/modules/classifier_stuff/cmd.sh"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout, stderr = p1.communicate()
output = p1.communicate()[0]
print('stdout:'+stdout+' stderr:'+stderr)
sys.stdout.flush()
p2=subprocess.Popen(["sudo /home/www-data/web2py/applications/fingerPrint/modules/classifier_stuff/cmd.sh"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout, stderr = p2.communicate()
print('stdout:'+stdout+' stderr:'+stderr)
sys.stdout.flush()

但我有

stdout: stderr:
Traceback (most recent call last):
File "prepare_and_train.py", line 56, in <module>
 p2=subprocess.Popen(["/home/www-data/web2py/applications/fingerPrint/modules/classifier_stuff/cmd.sh"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 26] Text file busy

如果我把PIPE改为STDOUT,我会得到一个有趣的

OSError: [Errno 9] Bad file descriptor

当我尝试子进程时,同样的"文件繁忙"。调用:

sudo: unable to execute ./cmd.sh: Text file busy
stdout: stderr:

我真的不在乎我怎么做,我只想要工作代码——这里有什么提示吗?我(很明显)是linux 的新手

您遇到的错误是因为您试图在脚本仍处于打开状态时执行脚本。特别是,请参阅以下最小示例:

#!/usr/bin/env python
import os
f = open('f.sh', 'w')
f.write("#!/bin/shnecho test")
os.chmod('f.sh', 0o755)
os.execl('f.sh', './f.sh')

如果你执行它,你会得到:

$ ./a.py 
Traceback (most recent call last):
  File "./a.py", line 8, in <module>
    os.execl('f.sh', './f.sh')
  File "/usr/lib64/python3.4/os.py", line 491, in execl
    execv(file, args)
OSError: [Errno 26] Text file busy

如果您确保在执行之前关闭文件,例如:

#!/usr/bin/env python
import os
with open('f.sh', 'w') as f:
    f.write("#!/bin/shnecho test")
os.chmod('f.sh', 0o755)
os.execl('f.sh', './f.sh')

它运行良好:

$ ./a.py 
test

进入你的具体问题,是第6行:

f.close

您缺少了括号,所以您不需要调用close()方法,而是简单地获取(而不是使用)它

f.close()

或者如在我的示例中那样以CCD_ 2语句为前导。

同时,您可能还想使用os.chmod(),而不是调用外部chmod工具。

"管道破裂"错误是正常的,对于任何连接到head或类似实用程序的管道来说都是意料之中的。

把事情分解一下,

  1. 进程一开始写入管道
  2. 过程二开始从管道读取
  3. 处理两次饰面并关闭管道
  4. 进程一试图向管道写入更多数据

当你没有很多输出时,(4)永远不会发生,所以你不会一直看到这个错误。但这是正常的,也是意料之中的。

无论如何,我会在Python中处理head部分。然后你也可以取消shell=True

find = subprocess.Popen(['find', rootDir + '/' + str(k), '-type', 'f'],
    stdout=subprocess.PIPE)
result = [find.stdout.readline() for x in xrange(10)]
find.terminate()
with open('negatives' + str(i) + 'txt', 'w') as output:
    output.write(''.join(result))

(你对find-iname "*"论点似乎没有任何用处,所以我把它省略了。)

具有讽刺意味的是,这在Python中比在"复杂"shell脚本中更不透明。当然,在纯Python中,您将使用os.walk()而不是find

最新更新