Why doesn't del delete it?











up vote
3
down vote

favorite
1












The code below creates a "tee" object that tees stdout to a file as well as the terminal.



If do del t as below when I'm done tee-ing, the object doesn't get deleted and the __del__() member doesn't get called (so the tee-ing continues):



t = tee("foo.txt")
print("bar")
del t


But if I call __del__() directly, things work fine:



t = tee("foo.txt")
print("bar")
t.__del__()


Why doesn't the del work? What's the right way to do this?



class tee():
def __init__(self, filepath):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath

sys.stdout = self
sys.stderr = self

def write(self, text):
self.old_stdout.write(text)
with open(self.name, 'a', encoding="utf-8") as f:
f.write(text)

def flush(self):
pass

def __del__(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr









share|improve this question


















  • 5




    del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
    – UnholySheep
    Nov 11 at 18:17

















up vote
3
down vote

favorite
1












The code below creates a "tee" object that tees stdout to a file as well as the terminal.



If do del t as below when I'm done tee-ing, the object doesn't get deleted and the __del__() member doesn't get called (so the tee-ing continues):



t = tee("foo.txt")
print("bar")
del t


But if I call __del__() directly, things work fine:



t = tee("foo.txt")
print("bar")
t.__del__()


Why doesn't the del work? What's the right way to do this?



class tee():
def __init__(self, filepath):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath

sys.stdout = self
sys.stderr = self

def write(self, text):
self.old_stdout.write(text)
with open(self.name, 'a', encoding="utf-8") as f:
f.write(text)

def flush(self):
pass

def __del__(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr









share|improve this question


















  • 5




    del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
    – UnholySheep
    Nov 11 at 18:17















up vote
3
down vote

favorite
1









up vote
3
down vote

favorite
1






1





The code below creates a "tee" object that tees stdout to a file as well as the terminal.



If do del t as below when I'm done tee-ing, the object doesn't get deleted and the __del__() member doesn't get called (so the tee-ing continues):



t = tee("foo.txt")
print("bar")
del t


But if I call __del__() directly, things work fine:



t = tee("foo.txt")
print("bar")
t.__del__()


Why doesn't the del work? What's the right way to do this?



class tee():
def __init__(self, filepath):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath

sys.stdout = self
sys.stderr = self

def write(self, text):
self.old_stdout.write(text)
with open(self.name, 'a', encoding="utf-8") as f:
f.write(text)

def flush(self):
pass

def __del__(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr









share|improve this question













The code below creates a "tee" object that tees stdout to a file as well as the terminal.



If do del t as below when I'm done tee-ing, the object doesn't get deleted and the __del__() member doesn't get called (so the tee-ing continues):



t = tee("foo.txt")
print("bar")
del t


But if I call __del__() directly, things work fine:



t = tee("foo.txt")
print("bar")
t.__del__()


Why doesn't the del work? What's the right way to do this?



class tee():
def __init__(self, filepath):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath

sys.stdout = self
sys.stderr = self

def write(self, text):
self.old_stdout.write(text)
with open(self.name, 'a', encoding="utf-8") as f:
f.write(text)

def flush(self):
pass

def __del__(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr






python






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 11 at 18:14









nerdfever.com

703619




703619








  • 5




    del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
    – UnholySheep
    Nov 11 at 18:17
















  • 5




    del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
    – UnholySheep
    Nov 11 at 18:17










5




5




del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
– UnholySheep
Nov 11 at 18:17






del only unbinds the variable name, it does not guarantee that the object gets destroyed immediately, as stated in the docs: docs.python.org/3/reference/datamodel.html#object.__del__
– UnholySheep
Nov 11 at 18:17














2 Answers
2






active

oldest

votes

















up vote
7
down vote














Note del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero.

Taken from the data model section of the Python 3 documentation.




You've referenced the class inside the constructor:



sys.stdout = self
sys.stderr = self


The reference will remain and as a result the object will stay “alive”.






share|improve this answer























  • But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
    – nerdfever.com
    Nov 11 at 18:19












  • @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
    – Adam Smith
    Nov 11 at 18:21










  • @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
    – Paritosh Singh
    Nov 11 at 18:24






  • 8




    @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
    – user2357112
    Nov 11 at 18:24










  • @user2357112 Make than an answer and I'll accept it. (Thanks.)
    – nerdfever.com
    Nov 11 at 18:25


















up vote
2
down vote













What you’re actually looking for is the with-statement that is used for a specific context. You open the file, do something with it and close it again.



with tree(“foo.txt) as t:
t.write(“bar”)


This will call the exit method in the end.



class tee():
def __init__(self, filepath):
self.old_stdout = sys.stdout
self.old_stderr = sys.stderr
self.name = filepath

sys.stdout = self
sys.stderr = self

def write(self, text):
self.old_stdout.write(text)
with open(self.name, 'a', encoding="utf-8") as f:
f.write(text)

def flush(self):
pass

def __exit__(self):
sys.stdout = self.old_stdout
sys.stdout = self.old_stderr


Actually your class is doing the same thing with the file handler in the write method.



For the delete method: As the others already mentioned, the delete statement will just decrement the reference counter. Once the number of references has reached zero, the object will be garbage collected and the delete method will be invoked. But this won’t happen in your case since the object is still referenced by the standard output.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53251738%2fwhy-doesnt-del-object-delete-it%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    7
    down vote














    Note del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero.

    Taken from the data model section of the Python 3 documentation.




    You've referenced the class inside the constructor:



    sys.stdout = self
    sys.stderr = self


    The reference will remain and as a result the object will stay “alive”.






    share|improve this answer























    • But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
      – nerdfever.com
      Nov 11 at 18:19












    • @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
      – Adam Smith
      Nov 11 at 18:21










    • @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
      – Paritosh Singh
      Nov 11 at 18:24






    • 8




      @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
      – user2357112
      Nov 11 at 18:24










    • @user2357112 Make than an answer and I'll accept it. (Thanks.)
      – nerdfever.com
      Nov 11 at 18:25















    up vote
    7
    down vote














    Note del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero.

    Taken from the data model section of the Python 3 documentation.




    You've referenced the class inside the constructor:



    sys.stdout = self
    sys.stderr = self


    The reference will remain and as a result the object will stay “alive”.






    share|improve this answer























    • But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
      – nerdfever.com
      Nov 11 at 18:19












    • @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
      – Adam Smith
      Nov 11 at 18:21










    • @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
      – Paritosh Singh
      Nov 11 at 18:24






    • 8




      @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
      – user2357112
      Nov 11 at 18:24










    • @user2357112 Make than an answer and I'll accept it. (Thanks.)
      – nerdfever.com
      Nov 11 at 18:25













    up vote
    7
    down vote










    up vote
    7
    down vote










    Note del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero.

    Taken from the data model section of the Python 3 documentation.




    You've referenced the class inside the constructor:



    sys.stdout = self
    sys.stderr = self


    The reference will remain and as a result the object will stay “alive”.






    share|improve this answer















    Note del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero.

    Taken from the data model section of the Python 3 documentation.




    You've referenced the class inside the constructor:



    sys.stdout = self
    sys.stderr = self


    The reference will remain and as a result the object will stay “alive”.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 12 at 15:22









    asynts

    7241720




    7241720










    answered Nov 11 at 18:18









    Liumatt

    13215




    13215












    • But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
      – nerdfever.com
      Nov 11 at 18:19












    • @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
      – Adam Smith
      Nov 11 at 18:21










    • @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
      – Paritosh Singh
      Nov 11 at 18:24






    • 8




      @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
      – user2357112
      Nov 11 at 18:24










    • @user2357112 Make than an answer and I'll accept it. (Thanks.)
      – nerdfever.com
      Nov 11 at 18:25


















    • But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
      – nerdfever.com
      Nov 11 at 18:19












    • @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
      – Adam Smith
      Nov 11 at 18:21










    • @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
      – Paritosh Singh
      Nov 11 at 18:24






    • 8




      @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
      – user2357112
      Nov 11 at 18:24










    • @user2357112 Make than an answer and I'll accept it. (Thanks.)
      – nerdfever.com
      Nov 11 at 18:25
















    But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
    – nerdfever.com
    Nov 11 at 18:19






    But in the code above there's only one reference to 't'. So the refcount should reach zero at 'del t'. No?
    – nerdfever.com
    Nov 11 at 18:19














    @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
    – Adam Smith
    Nov 11 at 18:21




    @nerdfever.com I assume GC takes care of calling x.__del__ once there are no references exist to it.
    – Adam Smith
    Nov 11 at 18:21












    @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
    – Paritosh Singh
    Nov 11 at 18:24




    @nerdfever.com the gc doesn't run after every line or check every variable all the time, that would be too "expensive". It just does its thing every now and then, and has a hierarchy of variables to check reference counts for.
    – Paritosh Singh
    Nov 11 at 18:24




    8




    8




    @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
    – user2357112
    Nov 11 at 18:24




    @nerdfever.com: You seem to have forgotten about the two references you stored in sys.stdout and sys.stderr.
    – user2357112
    Nov 11 at 18:24












    @user2357112 Make than an answer and I'll accept it. (Thanks.)
    – nerdfever.com
    Nov 11 at 18:25




    @user2357112 Make than an answer and I'll accept it. (Thanks.)
    – nerdfever.com
    Nov 11 at 18:25












    up vote
    2
    down vote













    What you’re actually looking for is the with-statement that is used for a specific context. You open the file, do something with it and close it again.



    with tree(“foo.txt) as t:
    t.write(“bar”)


    This will call the exit method in the end.



    class tee():
    def __init__(self, filepath):
    self.old_stdout = sys.stdout
    self.old_stderr = sys.stderr
    self.name = filepath

    sys.stdout = self
    sys.stderr = self

    def write(self, text):
    self.old_stdout.write(text)
    with open(self.name, 'a', encoding="utf-8") as f:
    f.write(text)

    def flush(self):
    pass

    def __exit__(self):
    sys.stdout = self.old_stdout
    sys.stdout = self.old_stderr


    Actually your class is doing the same thing with the file handler in the write method.



    For the delete method: As the others already mentioned, the delete statement will just decrement the reference counter. Once the number of references has reached zero, the object will be garbage collected and the delete method will be invoked. But this won’t happen in your case since the object is still referenced by the standard output.






    share|improve this answer



























      up vote
      2
      down vote













      What you’re actually looking for is the with-statement that is used for a specific context. You open the file, do something with it and close it again.



      with tree(“foo.txt) as t:
      t.write(“bar”)


      This will call the exit method in the end.



      class tee():
      def __init__(self, filepath):
      self.old_stdout = sys.stdout
      self.old_stderr = sys.stderr
      self.name = filepath

      sys.stdout = self
      sys.stderr = self

      def write(self, text):
      self.old_stdout.write(text)
      with open(self.name, 'a', encoding="utf-8") as f:
      f.write(text)

      def flush(self):
      pass

      def __exit__(self):
      sys.stdout = self.old_stdout
      sys.stdout = self.old_stderr


      Actually your class is doing the same thing with the file handler in the write method.



      For the delete method: As the others already mentioned, the delete statement will just decrement the reference counter. Once the number of references has reached zero, the object will be garbage collected and the delete method will be invoked. But this won’t happen in your case since the object is still referenced by the standard output.






      share|improve this answer

























        up vote
        2
        down vote










        up vote
        2
        down vote









        What you’re actually looking for is the with-statement that is used for a specific context. You open the file, do something with it and close it again.



        with tree(“foo.txt) as t:
        t.write(“bar”)


        This will call the exit method in the end.



        class tee():
        def __init__(self, filepath):
        self.old_stdout = sys.stdout
        self.old_stderr = sys.stderr
        self.name = filepath

        sys.stdout = self
        sys.stderr = self

        def write(self, text):
        self.old_stdout.write(text)
        with open(self.name, 'a', encoding="utf-8") as f:
        f.write(text)

        def flush(self):
        pass

        def __exit__(self):
        sys.stdout = self.old_stdout
        sys.stdout = self.old_stderr


        Actually your class is doing the same thing with the file handler in the write method.



        For the delete method: As the others already mentioned, the delete statement will just decrement the reference counter. Once the number of references has reached zero, the object will be garbage collected and the delete method will be invoked. But this won’t happen in your case since the object is still referenced by the standard output.






        share|improve this answer














        What you’re actually looking for is the with-statement that is used for a specific context. You open the file, do something with it and close it again.



        with tree(“foo.txt) as t:
        t.write(“bar”)


        This will call the exit method in the end.



        class tee():
        def __init__(self, filepath):
        self.old_stdout = sys.stdout
        self.old_stderr = sys.stderr
        self.name = filepath

        sys.stdout = self
        sys.stderr = self

        def write(self, text):
        self.old_stdout.write(text)
        with open(self.name, 'a', encoding="utf-8") as f:
        f.write(text)

        def flush(self):
        pass

        def __exit__(self):
        sys.stdout = self.old_stdout
        sys.stdout = self.old_stderr


        Actually your class is doing the same thing with the file handler in the write method.



        For the delete method: As the others already mentioned, the delete statement will just decrement the reference counter. Once the number of references has reached zero, the object will be garbage collected and the delete method will be invoked. But this won’t happen in your case since the object is still referenced by the standard output.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 12 at 16:15

























        answered Nov 11 at 19:46









        Matthias

        2,18523376




        2,18523376






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53251738%2fwhy-doesnt-del-object-delete-it%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Florida Star v. B. J. F.

            Error while running script in elastic search , gateway timeout

            Adding quotations to stringified JSON object values