简体   繁体   English

OSError:[Errno 36]使用Popen时文件名太长-Python

[英]OSError: [Errno 36] File name too long while using Popen - Python

As I started asking on a previous question, I'm extracting a tarball using the tarfile module of python. 当我开始询问上一个问题时,我正在使用python的tarfile模块提取一个tarball。 I don't want the extracted files to be written on the disk, but rather get piped directly to another program, specifically bgzip. 我不希望将提取的文件写在磁盘上,而是直接通过管道传输到另一个程序,特别是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

But now I get stuck on this: 但是现在我陷入了困境:

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

Is there any workaround for this? 有什么解决方法吗? I have been using the LightTableLinux.tar.gz (it contains the files for a text editor program) as a tarball to test the script on it. 我一直在使用LightTableLinux.tar.gz (其中包含文本编辑器程序的文件)作为压缩包来测试其上的脚本。

The exception is raised in the forked-off child process when trying to execute the target program from this invocation: 尝试从此调用执行目标程序时,在分支的子进程中引发异常:

proc = subprocess.Popen(tar.extractfile(file).read(), stdout = subprocess.PIPE)

This 这个

  1. reads the contents of an entry in the tar file 读取tar文件中条目的内容
  2. tries to execute a program with the name of the contents of that entry. 尝试使用该条目内容的名称执行程序。

Also your second invocation won't work, as you are trying to use shell redirection without using shell=True in Popen() : 另外,您的第二次调用将不起作用,因为您尝试使用Shell重定向而不在Popen()使用shell=True

proc2 = subprocess.Popen('bgzip -c > ' + clean(mov), stdin = proc, stdout = subprocess.PIPE) 

The redirect may also not be necessary, as you should be able to simply redirect the output from bgzip to a file from python directly. 重定向也可能不是必需的,因为您应该能够直接将bgzip的输出重定向到python的文件。

Edit: Unfortunately, despite extractfile() returning a file-like object , Popen() expects a real file (with a fileno ). 编辑:不幸的是,尽管extractfile()返回一个类文件对象Popen()需要一个真正的file (用fileno )。 Hence, a little wrapping is required: 因此,需要一些包装:

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM