Python 2.6.4 marshal.load不';t接受用subprocess.Popen创建的打开文件对象

Python 2.6.4 marshal.load不';t接受用subprocess.Popen创建的打开文件对象,python,Python,这真是一个不幸的情况。Maya 2011附带2.6.4,但此代码在其中不起作用: pipe = subprocess.Popen( 'p4 -G edit C:/somefile.txt', stdout=subprocess.PIPE).stdout try: while 1: record = marshal.load( pipe ) list.append( record ) except EOFError: pass 各种2.5版本都可

这真是一个不幸的情况。Maya 2011附带2.6.4,但此代码在其中不起作用:

pipe = subprocess.Popen( 'p4 -G edit C:/somefile.txt', stdout=subprocess.PIPE).stdout

try:
    while 1:
        record = marshal.load( pipe )
        list.append( record )
except EOFError:
    pass
各种2.5版本都可以使用,最新的2.6.5也可以使用,当然,这不是Maya附带的版本!它抛出以下错误:

# Error: TypeError: file <maya console> line 3: marshal.load() arg must be file #
我不知道为什么它会起作用(在2.5.x/2.6.5中),但它确实起作用;listData最终成为所有文件结果的列表。我不知道如何使用marshal.loads()执行此操作,我只返回第一个结果。这种方法几乎是一字不差的,所以我知道这是做事的方式。很容易想象,我只是不知道如何正确使用子流程和封送处理

更新2 marshal.loads()完全有效

经过更多测试后,pipe.read()提供了所有数据,但它包含一些空字符或其他我不完全理解的内容,因此marshal.loads()只读取第一个条目。在这种特殊情况下,我可以拆分“{”上的数据并收集数据

listData = []
results = pipe.read().split("{")
# Skip the first entry since it's empty
for result in results[1:]:
    listData.append( marshal.loads( "{" + result) )

感谢克里斯蒂安为我指明了正确的方向,希望任何使用perforce升级到Maya 2011的人都能让事情变得更顺利。

在使用-G选项解组p4的输出时遇到了同样的问题。
marshal.load(str)
只读取第一条记录,
marshal.load(StringIO(str))
因“marshal.load()参数必须是文件”而失败。 建议我使用临时文件解决方案,而不是拆分:

import subprocess, marshal, tempfile

tempf = tempfile.TemporaryFile()
subprocess.Popen(cmd, stdout=tempf).communicate()
tempf.seek(0)
try:
    while 1:
        record = marshal.load(tempf)
        listData.append( record )
except EOFError:
    pass
tempf.close()

请注意,python会在您关闭临时文件后立即为您删除它。

这是一个老问题,但我想我应该添加我为遇到此问题的其他人找到的内容

不幸的是,senyacap的答案在Windows上似乎不起作用,
marshal.load(tempf)
无法说明临时文件不是文件对象。传入
tempf.file
也不起作用

因此,另一个(可怕的)解决办法是(这是专门用于处理Perforce的,因为没有其他选项可以使用
封送
模块),这是:

p = subprocess.Popen ( cmd, stdout = subprocess.PIPE ) 
( stdoutdata, stderrdata ) = p.communicate ( )

unmarshalled = []
while stdoutdata:
    record = marshal.loads ( stdoutdata )
    unmarshalled.append ( record )
    remarshalled = marshal.dumps ( record )
    stdoutdata = stdoutdata [ len ( remarshalled ) : ]

最后,我选择了这个

import shutil
import os
import tempfile

def decode_list(outputstr):
  tmpfolder = tempfile.mkdtemp()
  try:
      binname = os.path.join(tmpfolder, "p4_decode.bin")
      with open(binname, "wb") as binfile:
          binfile.write(outputstr)

      with open(binname, "rb") as binfile:
          ret = []
          while True:
              try:
                  item = marshal.load(binfile)
                  ret.append(item)
              except EOFError:
                  return ret
  finally:
      if tmpfolder and os.path.isdir(tmpfolder):
          shutil.rmtree(tmpfolder)

你试过使用
marshal.loads
?我知道它效率较低,但至少它应该可以工作。我更新了帖子,对marshal.loads()的探索不成功。我将继续尝试,但到目前为止,最终的答案仍然是我找不到的。关于“拆分
{
字符”方法-不要这样做!不能保证
{
byte不会出现在封送的数据中。然后,您的解组将失败。我刚刚从
p4-G changes…
命令的输出中遇到了这种情况。请注意,对于Python>=2.4,您应该将
version
参数的
0
传递到
封送。转储
。p4使用旧版本0格式,但您的Python安装可能会使用更新的东西,从而产生不同的结果。
import shutil
import os
import tempfile

def decode_list(outputstr):
  tmpfolder = tempfile.mkdtemp()
  try:
      binname = os.path.join(tmpfolder, "p4_decode.bin")
      with open(binname, "wb") as binfile:
          binfile.write(outputstr)

      with open(binname, "rb") as binfile:
          ret = []
          while True:
              try:
                  item = marshal.load(binfile)
                  ret.append(item)
              except EOFError:
                  return ret
  finally:
      if tmpfolder and os.path.isdir(tmpfolder):
          shutil.rmtree(tmpfolder)