当我开始询问上一个问题时,我正在使用python的tarfile模块提取tarball。我不希望将提取的文件写在磁盘上,而是直接通过管道传输到另一个程序,特别是bgzip。
#!/usr/bin/env python
import tarfile, subprocess, re
mov = []
def clean(s):
s = re.sub('[^0-9a-zA-Z_]', '', s)
s = re.sub('^[^a-zA-Z_]+', '', s)
return s
with tarfile.open("SomeTarballHere.tar.gz", "r:gz") as tar:
for file in tar.getmembers():
if file.isreg():
mov = file.name
proc = subprocess.Popen(tar.extractfile(file).read(), stdout = subprocess.PIPE)
proc2 = subprocess.Popen('bgzip -c > ' + clean(mov), stdin = proc, stdout = subprocess.PIPE)
mov = None
但现在我对此感到困惑:
Traceback (most recent call last):
File "preformat.py", line 12, in <module>
proc = subprocess.Popen(tar.extractfile(file).read(), stdout = subprocess.PIPE)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 36] File name too long
这有什么解决方法吗?我一直在使用LightTableLinux.tar.gz
(它包含文本编辑器程序的文件)作为tarball来测试它上面的脚本。
答案 0 :(得分:1)
尝试从此调用执行目标程序时,在分叉子进程中引发异常:
proc = subprocess.Popen(tar.extractfile(file).read(), stdout = subprocess.PIPE)
此
此外,您的第二次调用无效,因为您尝试使用shell重定向而不使用shell=True
中的Popen()
:
proc2 = subprocess.Popen('bgzip -c > ' + clean(mov), stdin = proc, stdout = subprocess.PIPE)
重定向也可能没有必要,因为您应该能够直接将bgzip
的输出重定向到python中的文件。
修改:很遗憾,尽管extractfile()
返回类似文件的对象,但Popen()
仍需要真实的file
(fileno
}。因此,需要一点包装:
with tar.extractfile(file) as tarfile, file(clean(mov), 'wb') as outfile:
proc = subprocess.Popen(
('bgzip', '-c'),
stdin=subprocess.PIPE,
stdout=outfile,
)
shutil.copyfileobj(tarfile, proc.stdin)
proc.stdin.close()
proc.wait()