Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 酸洗不可涂刷的物体_Python_Pygame_Pickle_Save_Savestate - Fatal编程技术网

Python 酸洗不可涂刷的物体

Python 酸洗不可涂刷的物体,python,pygame,pickle,save,savestate,Python,Pygame,Pickle,Save,Savestate,我正在用pygame制作一个绘图程序,我想给用户一个选项,保存程序的精确状态,然后在以后重新加载。 在这一点上,我保存了我的globalsdict的一个副本,然后迭代,对每个对象进行酸洗。pygame中的某些对象无法进行pickle,但可以转换为字符串并以这种方式进行pickle。我的代码就是这样设置的,但其中一些不可拼接的对象是通过引用访问的。换句话说,它们不在全局字典中,但被全局字典中的对象引用。我想在这个递归中对它们进行pickle,但我不知道如何告诉pickle返回它遇到问题的对象,更改

我正在用pygame制作一个绘图程序,我想给用户一个选项,保存程序的精确状态,然后在以后重新加载。 在这一点上,我保存了我的globalsdict的一个副本,然后迭代,对每个对象进行酸洗。pygame中的某些对象无法进行pickle,但可以转换为字符串并以这种方式进行pickle。我的代码就是这样设置的,但其中一些不可拼接的对象是通过引用访问的。换句话说,它们不在全局字典中,但被全局字典中的对象引用。我想在这个递归中对它们进行pickle,但我不知道如何告诉pickle返回它遇到问题的对象,更改它,然后再次尝试pickle。我的代码真的很混乱,如果有一种不同的、更好的方法来做我想做的事情,请告诉我


surfaceStringHeader = 'PYGAME.SURFACE_CONVERTED:'
imageToStringFormat = 'RGBA'
def save_project(filename=None):
    assert filename != None, "Please specify path of project file"
    pickler = pickle.Pickler(file(filename,'w'))
    for key, value in globals().copy().iteritems():
        #There's a bit of a kludge statement here since I don't know how to 
        #access module type object directly
        if type(value) not in [type(sys),type(None)]   and \
        key not in ['__name__','value','key']          and \
        (key,value) not in pygame.__dict__.iteritems() and \
        (key,value) not in sys.__dict__.iteritems()    and \
        (key,value) not in pickle.__dict__.iteritems(): 
        #Perhaps I should add something to the above to reduce redundancy of
        #saving the program defaults?
            #Refromat unusable objects:
            if type(value)==pygame.Surface:
                valueString = pygame.image.tostring(value,imageToStringFormat)
                widthString = str(value.get_size()[0]).zfill(5)
                heightString = str(value.get_size()[1]).zfill(5)
                formattedValue = surfaceStringHeader+widthString+heightString+valueString
            else:
                formattedValue = value

            try:
                pickler.dump((key,formattedValue))
            except Exception as e:
                print key+':' + str(e)

def open_project(filename=None):
    assert filename != None, "Please specify path to project file"
    unpickler = pickle.Unpickler(file(filename,'r'))
    haventReachedEOF = False
    while haventReachedEOF:
        try:
            key,value = unpickler.load()
            #Rework the unpicklable objects stored 
            if type(value) == str and value[0:25]==surfaceStringHeader:
                value = pygame.image.frombuffer(value[36:],(int(value[26:31]),int(value[31:36])),imageToStringFormat)
            sys.modules['__main__'].__setattr__(key,value)
        except EOFError:
            haventReachedEOF = True

简言之:不要这样做


对应用程序中的所有内容进行酸洗会造成混乱,并可能导致问题。从程序中获取所需的数据,并手动将其存储在适当的数据格式中,然后通过从该数据中创建所需的内容来加载数据。

从您的评论中,您尝试做的最困难的部分似乎是为用户提供一个实时解释器,并保存该解释器的状态

那么,作为子进程运行实时解释器怎么样?要将对象模型中的任何信息公开给脚本,都可以显式地公开(无论是通过
多处理
共享内存还是某种消息传递API)

然后,您不需要保存自己的解释器的完整状态,这要么非常困难,要么不可能;以正常方式保存数据模型,然后可以从外部而不是内部冻结子解释器

这显然比你想做的要复杂得多,但我不认为任何简单的事情都能奏效。例如,如果用户有一个带代码的实时解释器,他们可以修补任何东西,甚至是酸洗代码,然后会发生什么?您需要定义一些关于可以保存和恢复哪些内容的限制,如果这些限制足够广泛,我认为您必须从外部执行


同时,正如一篇评论中提到的,
scipy
(或Enthound附带的一些相关项目)和
ipython
都具有针对有限用例的保存和恢复功能,这至少为您提供了一些可供研究的代码,但是它们的用例可能与您的不一样。

如果您知道所有不可点击的对象类型,那么这个问题答案中的代码可能会有所帮助“”--我写这篇文章是为了回应类似的情况,我知道所有不可点击的对象类型,但我不知道它们在数据结构中的位置。您可以使用此代码查找它们,用其他代码替换它们,然后在取消勾选时使用类似的代码将它们放回。

您希望保存整个程序的状态,以便以后可以重新加载。这是一个完美的Pickle用例,我看不出这个用例有任何问题。然而,您清除globals()名称空间并过滤掉sys、pygame和pickle的方法是不可靠的。通常的模式是使用一个会话对象进行pickle

此外,我认为可能会对如何泡菜产生一些困惑:

  • pickle对象时,其引用的所有对象 成员变量将自动pickle/unpickle,这是 好
  • 如果pickle无法序列化对象,应该告诉pickle 如何通过为任何没有pickle的对象编写自定义方法来保存和恢复该对象,所以 嵌套在master中的一个或两个类 会话对象将具有自定义的get/setstate函数 像重新打开设备之类的东西,比如文件句柄,显然会 不同的会议
  • 如果需要进行二进制序列化 您不需要将对象强制转换为字符串,只需使用二进制文件即可 该对象的get/setstate方法中的序列化协议, ()
  • 最后,您的代码应该更像这样:

    session = None
    import pickle
    def startsession():
        globals session
        session = pickle.Unpickler(sessionfilehandle('r')).load()
        if session is None: session = Session() 
    
    def savesession(filename=None):
        globals session
        pickle.Pickler.dump(session,sessionfilehandle('w'))
    
    class Session(object):
        def __init__(self):
            self.someobject=NewObject1()
            #.... plus whole object tree representing the whole game
            self.somedevicehandlethatcannotbepickled=GetDeviceHandle1()  #for example
        def __getstate__(self):
            odict = self.__dict__.copy()
            del odict['somedevicehandlethatcannotbepickled'] #don't pickle this
            return odict
        def __setstate__(self, dict):
            self.__dict__.update(dict)
            self.somedevicehandlethatcannotbepickled=GetDeviceHandle1()
    
    为此,我使用,它可以序列化python中的几乎所有内容。Dill还可以帮助您理解代码失败时是什么导致酸洗失败。此外,这也是对测试套件的一个非常方便的补充

    >>> import dill
    >>> # blah blah blah... your session code here
    >>> dill.dump_session('pygame.pkl')
    >>>
    >>> # and if you get a pickling error, use dill's tools to discover a workaround
    >>> dill.detect.badobjects(your_bad_object, depth=1)
    >>>
    >>> # visualize the references in your bad objects
    >>> objgraph.show_refs(your_bad_object, filename='pygame_bad_object.png')
    

    这辆车看起来很笨重。明确你想要保存的价值观,这样你就不会有很多麻烦了。根据经验,我可以说,精确定义程序的状态是一项前期工作,但它鼓励更好的设计,并迫使您仔细考虑自己的状态(这在调试时很方便)。问题的难点在于,程序的状态包括为用户运行实时解释器,可用于修改图形的状态。你在最初的问题中没有提到这一点。该程序与一个实时解释器一起运行,允许用户重写或添加函数和数据结构。我希望在加载项目时保留并重新定义这些变量,因此我不能将pickle限制为预定义变量。没有办法保存python程序的状态吗?@hedgehogrider:在任何情况下都无法保存python程序的完整状态。无论是
    ipython
    还是
    scipy
    对这个想法的实现都非常有限,超出了
    pickle
    (就此而言,
    多处理
    pickle
    扩展到了库存之外),因此您可能需要向他们寻求想法。但是,您是否需要用户能够(例如)将monkeypatch作为您框架的一部分并使其可恢复?您的建议并不是一项简单的任务。这是否可能超出了我的知识范围,但你可能想问问自己,这真的需要有这么多的空间。顺便说一句,我不知道