开发者

How do I override file.write() in Python 3?

开发者 https://www.devze.com 2023-01-03 07:56 出处:网络
The code below works on Python 2.6 but not on Python 3.x: old_file_write = file.write class file(): def write(self, d):

The code below works on Python 2.6 but not on Python 3.x:

old_file_write = file.write 

class file():
    def write(self, d):
        if isinstance(d, types.bytes):
            self.buffer.write(d)
        else:
            old_file_write(d)

# ... some code I cannot change or do not want to change
f = open("x")
f.write("...")
f.write(b"...")
sys.stdout.write(b"...")
sys.stdout.write("...")
print(b"...")
print("...")

The problem is that in Python 3.x the first line will generate an error:

NameError: name 'file' is not defined

How can I make this work in Python 3.x?

In fact, two years later, I'm still looking for a solution that will work on both versions (2.5+, and 3.x).

For those who are still wondering why I am looking for this, it is just in or开发者_StackOverflow中文版der to be able to make old code (others code, which sometimes you cannot modify) to work with newer versions of python.

This is not about my code, it's about how can you write some code that plays nicely with bad code :)


I see two problems.

1: Your file class isn't inheriting from any specific class. If I've interpreted the situation correctly, it should be a subclass of io.TextIOWrapper.

2: In both Python 2.6 and 3.x, the types module (which would need to be imported in the first place) has no element bytes. The recommended method is to just use bytes on its own.

Redone snippet:

import io, sys

class file(io.TextIOWrapper):
    def write(self, d, encoding=sys.getdefaultencoding()):
        if isinstance(d, bytes):
            d = d.decode(encoding)
        super().write(d)

old_stdout = sys.stdout    # In case you want to switch back to it again

sys.stdout = file(open(output_file_path, 'w').detach())  # You could also use 'a', 'a+', 'w+', 'r+', etc.

Now it should do what you want it to, using sys.stdout.write to the output file that you specify. (If you don't wish to write to a file on disk but instead wish to write to the default sys.stdout buffer, using sys.stdout = file(sys.stdout.detach()) would probably work.)

Do note that, since Python 3.x does not have the file class, but 2.6 does have the io module, you will have to use one of the classes of the io module. My above code is just an example, and if you want it to be more flexible you'll have to work that out on your own. That is, depending on what sort of file you're writing to/what mode you're writing to in, you'll probably want to use a different class in io.


old_file_write = file.write 

You're using the class-level method of the file class.

old_file_write(d)

Should never have worked. I believe you're still copying and pasting incorrectly.

I think you may have had

old_file_write(self,d)

Which might have worked.

Your approach is not very good. Think about this instead.

class MyKindOfFile( file ):
    def write(self, d):
        if isinstance(d, types.bytes):
            self.buffer.write(d)
        else:
            super( MyFindOfFile, write )(d)

This will work out a LOT better for you, since it uses simple inheritance in a more typical way.


file objects can write bytes, but you need to open the file in the correct mode

fp = open('file.bin', 'wb') # open in binary mode
fp.write(b"some bytes") 
pf.close()

If you want to write strings to the disk you need to encode them first.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号