Disclaimer: The word subclass in the title is not correct, but this is a reference to the old pytho2 only solution and I didn't know any better way of describing it.
The objective: I am looking for a way, that lets me do following in my existing code
- import
MyFile
at the beginning of a file - 'just' replace
open
with eitherMyFile
- replace
open(*args, *kwargs)
withMyFile(*args, *kwargs, special_param=True)
The code should behave exactly as before, but trigger some additional behavior at the opening time (before or after opening) of the file and when some methods are called (e.g. close()
before or after closing)
With exactly as before I mean, that the code is still working if I would replace globally open(
with MyFile(
(and add of course the import for MyFile
open
is not a class and can therefore not be subclassed. The old python2 only version however was implemented by subclassing file
(which is also not a class AFAIK, but the solution worked)
The old python2 only solution:
class MyFile(file):
def __init__(self, fname, mode, special_param=False):
# next line would be nice, but is not essential
# do_something_special_before_opening(self, special_param)
super(MyFile, self).__init__(fname, mode)
do_something_special_after_opening(self, special_param)
def close(self):
super(MyFile, self).close()
do_something_special_after_closing(self)
The way it would be used is:
from mymodule import MyFile
# and then use MyFile in the rest of the file
or
from mymodule import MyFile as open
# keep the rest of the file unchanged
As file
doesn't exist anymore in python.
There is already an answer on SO ( Porting a sub-class of python2 'file' class to python3 )
However this does not answer my question, as it suggests to inherit from io.FileIO
, as it expects bytes
to be written and not str
ings.
What is the best way to implement such a feature in python3 (should work for Linux and Windows)
In python3 the result of open()
does not always belong to the same class.
Example:
If opening in text mode a _io.TextIOWrapper
object is returned. If opening in binary write mode a _io.BufferedWriter
or _io.BufferedReader
is returned. If opening in binary mode with buffering=0
then _io.FileIO
is returned.
So one option could be to subclass _io.TextIOWrapper
, _io.BufferedWriter
, _io.BufferedReader
, _io.FileIO
, ... and create a factory returning one of these sub classes.
However I wonder if there's a more elegant way. With above approach I had to create quite some sub classes and to reimplement the entire logic of open, that determines which class to use for which combination of parameters.
Perhaps there is some trick with monkeypatching?