【问题标题】:OSError: [Errno 36] File name too long while using Popen - PythonOSError:[Errno 36] 使用 Popen 时文件名太长 - Python
【发布时间】:2015-05-28 12:36:43
【问题描述】:

当我开始询问上一个问题时,我正在使用 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(它包含文本编辑器程序的文件)作为压缩包来测试它的脚本。

【问题讨论】:

  • Popen(tar.extractfile(file).read()) 您正在传递 tarfile 中特定文件的 contents 作为要执行的程序名称。

标签: python pipe stdout


【解决方案1】:

尝试从此调用执行目标程序时,在分叉的子进程中引发异常:

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

这个

  1. 读取 tar 文件中条目的内容
  2. 尝试使用该条目内容的名称执行程序。

您的第二次调用也不起作用,因为您尝试使用 shell 重定向而不在 Popen() 中使用 shell=True

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

【讨论】:

  • 在这里查看我的答案:stackoverflow.com/a/30487599/1988874 你不能使用由 extractfile 创建的类文件对象,因为 Popen 想要一个具有真实文件号的文件对象。
  • @CyrillePontvieux:感谢您的更新。这实际上看起来应该在subprocess 的文档中提到,因为对我来说,文档实际上另有说明。已修复。
猜你喜欢
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多