TypeError:不能腌制文件对象webpy和subprocess

时间:2015-05-31 08:30:26

标签: python session pickle web.py

我正在努力使以下代码成为可能。但我一直得到" TypeError:不能腌制文件对象"错误。我是python和webpy的新手。任何人都可以告诉我如何实现这个代码。

import web 
import subprocess

web.config.debug = False
urls = ( 
   "/start", "start",
   "/end", "end"
)
app = web.application(urls, locals())
s = web.session.Session(app, web.session.DiskStore('sessions'), initializer={"p": None})

class start:
    def GET(self):
        s.p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        return ""

class end:
    def GET(self):
        out, err = s.p.communicate();
        return out 

if __name__ == "__main__":
    app.run()

我一直看到的错误是 _reduce_ex中的python27 / lib / python2.7 / copy_reg.py",第70行     引发TypeError,"不能腌制%s对象" %base。名称 TypeError:不能腌制文件对象

1 个答案:

答案 0 :(得分:1)

我,我自己,一个网络新手。然而,在做了一些“研究”之后,似乎webpy不能pickle subprocess.Popen对象[1]。 因此,让我们尝试以下方法 - 即在end响应中创建它并打印其输出。

换句话说:

import web 
import subprocess

web.config.debug = False
urls = ( 
   "/start", "start",
   "/end", "end"
)
app = web.application(urls, locals())
s = web.session.Session(
        app, web.session.DiskStore('sessions'), initializer={"p": None})

class start:
    def GET(self):
        s.p = ['ls', '-a']
        return ""

class end:
    def GET(self):
        out, err = subprocess.Popen(
                       s.p , stdout=subprocess.PIPE,
                       stderr=subprocess.PIPE).communicate()
        s.kill() # kill the session.
        return out 

if __name__ == "__main__":
    app.run()

[1]如你所见:

import pickle
import subprocess

with open('bla', 'wb') as f:
    pickle.dump(subprocess.Popen(['ls'],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE), f)

subprocess.Popen返回一个文件描述符,并从追溯中推断出pickle无法序列化文件描述符。

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib64/python2.7/pickle.py", line 1370, in dump
    Pickler(file, protocol).dump(obj)
  File "/usr/lib64/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib64/python2.7/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/usr/lib64/python2.7/pickle.py", line 419, in save_reduce
    save(state)
  File "/usr/lib64/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib64/python2.7/pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "/usr/lib64/python2.7/pickle.py", line 663, in _batch_setitems
    save(v)
  File "/usr/lib64/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "/usr/lib64/python2.7/copy_reg.py", line 70, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects

除此之外,Pickle documentation还提到它支持布尔值,整数,浮点数,复数,字符串,字节对象,字节数组和无。因此,它似乎毫无希望。

修改

如果您坚持创建进程'文件描述符,则在从客户端收到start请求时,您可以使用字典将会话映射到文件描述符。

应该是这样的:

s = web.session.Session(
        app, web.session.DiskStore('sessions'), initializer={"p": None})
session_map = {}

class start:
    def GET(self):
        session_map[s] = subprocess.Popen(['ls', '-a'],
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.PIPE)
        return ""

class end:
    def GET(self):
        out, err = session_process[s].communicate()
        session_process.pop(s, None)
        s.kill
        return out