简体   繁体   English

在python中深度复制sys.stdout的问题

[英]Problems with deepcopying sys.stdout in python

I have the following problem with copy.deepcopy. 我在copy.deepcopy中遇到以下问题。 It is to do with deepcopying sys.stdout 与复制sys.stdout有关

import sys, copy

class Example:
  def __init__(self, value, outa=sys.stdout):
    self.value = value
    self.outa = outa
  def saying_hello_world(self):
    print>>self.outa, "Hello world! My value is ", self.value

example_1 = Example(3)
example_1.saying_hello_world()

example_2 = copy.deepcopy(example_1)
example_2.value = 5
example_2.saying_hello_world()

Leads to error 导致错误

Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 6, in saying_hello_world
ValueError: I/O operation on closed file

For various reasons I need to deepcopy (as I change example_2 in various ways in my more complex situation, and so need a deepcopy). 由于各种原因,我需要进行深度复制(因为在更复杂的情况下以各种方式更改example_2,因此需要进行深度复制)。 However, when it deepcopies sys.stdout , it transfers it from outputting into thee screen and instead outputs it to a closed file, which then gets the error above. 但是,当它深度复制sys.stdout ,它会将其从输出转移到屏幕上,而是输出到一个关闭的文件中,然后该文件上面的错误。 An obvious solution to this is 一个明显的解决方案是

example_2 = copy.deepcopy(example_1)
example_2.outa = example_1.outa

Is there a better way around this? 有没有更好的办法解决这个问题? Or a better way of deepcopying? 还是更好的复制方式? Thank you! 谢谢!

You can write your own mechanism for deepcoping object using magicmethod __deepcopy__ 您可以使用magicmethod__deepcopy__编写自己的对象深度__deepcopy__机制

Here is working example for your code: 这是您的代码的工作示例:

import sys, copy

class Example:
  def __init__(self, value, outa=sys.stdout):
    self.value = value
    self.outa = outa

  def saying_hello_world(self):
    print>>self.outa, "Hello world! My value is ", self.value

  def __deepcopy__(self, memo):
      # deepcopy self.value, but pass just a reference of self.outa
      return Example(copy.deepcopy(self.value, memo), self.outa)


example_1 = Example(3)
example_1.saying_hello_world()

example_2 = copy.deepcopy(example_1)
example_2.value = 5
example_2.saying_hello_world()

It is not ideal (you'll need care if subclassing this, as deepcopy of child will return instance of parent!) but should give you an idea how to implement this in your real life application. 这不是理想的选择(如果将其子类化,则需要注意,因为child的Deepcopy将返回parent的实例!),但是应该给您一个想法,如何在您的实际应用程序中实现它。

You can customise how your instances are copied, and just share the output if it is sys.stdout , using the __deepcopy__ method: 您可以自定义实例的复制方式,并使用__deepcopy__方法共享输出(如果是sys.stdout

class Example:
    def __init__(self, value, outa=sys.stdout):
        self.value = value
        self.outa = outa
    def saying_hello_world(self):
        print >> self.outa, "Hello world! My value is ", self.value
    def __deepcopy__(self, memo):
        outa = self.outa if self.outa is sys.stdout else deepcopy(self.outa, memo)
        return Example(deepcopy(self.value, memo), outa)

You can adjust the logic for when to copy the outa attribute; 您可以调整何时复制outa属性的逻辑。 perhaps not copying anything that is an open file object is a good idea, for example, or never copying that attribute. 例如,也许不复制打开文件对象的任何内容是个好主意,或者永远不要复制该属性。

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

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