“except Foo as bar” causes “bar” to be removed from scope

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
11
down vote

favorite












Given the following code:



msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)


Can somebody explain why this causes the following output in Python 3?



Error happened
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(msg)
NameError: name 'msg' is not defined









share|improve this question



























    up vote
    11
    down vote

    favorite












    Given the following code:



    msg = "test"
    try:
    "a"[1]
    except IndexError as msg:
    print("Error happened")
    print(msg)


    Can somebody explain why this causes the following output in Python 3?



    Error happened
    Traceback (most recent call last):
    File "test.py", line 6, in <module>
    print(msg)
    NameError: name 'msg' is not defined









    share|improve this question

























      up vote
      11
      down vote

      favorite









      up vote
      11
      down vote

      favorite











      Given the following code:



      msg = "test"
      try:
      "a"[1]
      except IndexError as msg:
      print("Error happened")
      print(msg)


      Can somebody explain why this causes the following output in Python 3?



      Error happened
      Traceback (most recent call last):
      File "test.py", line 6, in <module>
      print(msg)
      NameError: name 'msg' is not defined









      share|improve this question















      Given the following code:



      msg = "test"
      try:
      "a"[1]
      except IndexError as msg:
      print("Error happened")
      print(msg)


      Can somebody explain why this causes the following output in Python 3?



      Error happened
      Traceback (most recent call last):
      File "test.py", line 6, in <module>
      print(msg)
      NameError: name 'msg' is not defined






      python python-3.x scoping






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 1 min ago









      Konrad Rudolph

      389k1007641015




      389k1007641015










      asked 3 hours ago









      knipknap

      2,28842834




      2,28842834






















          4 Answers
          4






          active

          oldest

          votes

















          up vote
          9
          down vote



          accepted










          Yes, as soon as the exception is raised and msg is assigned with the new exception object, the original object has no more reference and is therefore deleted. The new exception object is also deleted as soon as it leaves the except block.



          You can verify it by overriding the __del__ method of the object and the exception assigned to msg:



          class A:
          def __del__(self):
          print('object deleted')
          class E(Exception):
          def __del__(self):
          print('exception deleted')
          msg = A()
          try:
          raise E()
          except E as msg:
          print("Error happened")


          This outputs:



          object deleted
          Error happened
          exception deleted
          NameError: name 'msg' is not defined





          share|improve this answer
















          • 3




            Wow, them's some wonky scope rules.
            – Lightness Races in Orbit
            3 hours ago










          • It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
            – habnabit
            2 hours ago






          • 1




            @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
            – Giacomo Alzetta
            1 hour ago






          • 1




            It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
            – Shamtam
            52 mins ago







          • 2




            @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
            – Konrad Rudolph
            19 mins ago


















          up vote
          11
          down vote













          msg in the except clause is in the same scope as msg on the first line.



          But in Python 3 we have this new behavior too:




          When an exception has been assigned using as target, it is cleared at
          the end of the except clause. This is as if



          except E as N:
          foo


          was translated to



          except E as N:
          try:
          foo
          finally:
          del N



          so, you "overwrite msg" in the exception handler, and exiting the handler will delete the variable.






          share|improve this answer


















          • 1




            This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
            – Jeronimo
            2 hours ago


















          up vote
          2
          down vote













          Exception blocks delete the caught variable at the end of the block, but they do not have their own scopes. So the sequence of events goes:



          1) msg is set to some string in the local scope



          2) msg is set to an IndexError object in the same local scope as 1



          3) msg is deleted from the local scope when the Exception block ends



          4) msg is no longer defined in the local scope, so the attempt to access it fails






          share|improve this answer








          New contributor




          Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.
























            up vote
            -4
            down vote













            because indentation matters. you were running msg outside of that try/except local scope



            msg = "test"
            try:
            "a"[1]
            except IndexError as msg:
            print("Error happened")
            print(msg)


            as per @Lightness Races in Orbit suggestion, here's how i'd rephrase my answer:



            when msg is cast/pointed as IndexError, it overloaded old msg, thus only lives within try/except scope.

            local scope here means relative to try/except, not '__main__', where the old msg = 'test' lives together with try/except. proof is in the code up there.






            share|improve this answer






















            • msg existed already before that scope, so that's not the problem.
              – Jeronimo
              3 hours ago










            • except IndexError as msg: overloaded msg
              – cryptonome
              3 hours ago










            • No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
              – Lightness Races in Orbit
              3 hours ago











            • @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
              – cryptonome
              3 hours ago











            • @cryptonome try-except doesn't introduce a new scope.
              – habnabit
              2 hours ago










            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: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            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%2f52965952%2fexcept-foo-as-bar-causes-bar-to-be-removed-from-scope%23new-answer', 'question_page');

            );

            Post as a guest






























            4 Answers
            4






            active

            oldest

            votes








            4 Answers
            4






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            9
            down vote



            accepted










            Yes, as soon as the exception is raised and msg is assigned with the new exception object, the original object has no more reference and is therefore deleted. The new exception object is also deleted as soon as it leaves the except block.



            You can verify it by overriding the __del__ method of the object and the exception assigned to msg:



            class A:
            def __del__(self):
            print('object deleted')
            class E(Exception):
            def __del__(self):
            print('exception deleted')
            msg = A()
            try:
            raise E()
            except E as msg:
            print("Error happened")


            This outputs:



            object deleted
            Error happened
            exception deleted
            NameError: name 'msg' is not defined





            share|improve this answer
















            • 3




              Wow, them's some wonky scope rules.
              – Lightness Races in Orbit
              3 hours ago










            • It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
              – habnabit
              2 hours ago






            • 1




              @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
              – Giacomo Alzetta
              1 hour ago






            • 1




              It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
              – Shamtam
              52 mins ago







            • 2




              @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
              – Konrad Rudolph
              19 mins ago















            up vote
            9
            down vote



            accepted










            Yes, as soon as the exception is raised and msg is assigned with the new exception object, the original object has no more reference and is therefore deleted. The new exception object is also deleted as soon as it leaves the except block.



            You can verify it by overriding the __del__ method of the object and the exception assigned to msg:



            class A:
            def __del__(self):
            print('object deleted')
            class E(Exception):
            def __del__(self):
            print('exception deleted')
            msg = A()
            try:
            raise E()
            except E as msg:
            print("Error happened")


            This outputs:



            object deleted
            Error happened
            exception deleted
            NameError: name 'msg' is not defined





            share|improve this answer
















            • 3




              Wow, them's some wonky scope rules.
              – Lightness Races in Orbit
              3 hours ago










            • It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
              – habnabit
              2 hours ago






            • 1




              @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
              – Giacomo Alzetta
              1 hour ago






            • 1




              It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
              – Shamtam
              52 mins ago







            • 2




              @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
              – Konrad Rudolph
              19 mins ago













            up vote
            9
            down vote



            accepted







            up vote
            9
            down vote



            accepted






            Yes, as soon as the exception is raised and msg is assigned with the new exception object, the original object has no more reference and is therefore deleted. The new exception object is also deleted as soon as it leaves the except block.



            You can verify it by overriding the __del__ method of the object and the exception assigned to msg:



            class A:
            def __del__(self):
            print('object deleted')
            class E(Exception):
            def __del__(self):
            print('exception deleted')
            msg = A()
            try:
            raise E()
            except E as msg:
            print("Error happened")


            This outputs:



            object deleted
            Error happened
            exception deleted
            NameError: name 'msg' is not defined





            share|improve this answer












            Yes, as soon as the exception is raised and msg is assigned with the new exception object, the original object has no more reference and is therefore deleted. The new exception object is also deleted as soon as it leaves the except block.



            You can verify it by overriding the __del__ method of the object and the exception assigned to msg:



            class A:
            def __del__(self):
            print('object deleted')
            class E(Exception):
            def __del__(self):
            print('exception deleted')
            msg = A()
            try:
            raise E()
            except E as msg:
            print("Error happened")


            This outputs:



            object deleted
            Error happened
            exception deleted
            NameError: name 'msg' is not defined






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 3 hours ago









            blhsing

            24.1k41134




            24.1k41134







            • 3




              Wow, them's some wonky scope rules.
              – Lightness Races in Orbit
              3 hours ago










            • It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
              – habnabit
              2 hours ago






            • 1




              @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
              – Giacomo Alzetta
              1 hour ago






            • 1




              It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
              – Shamtam
              52 mins ago







            • 2




              @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
              – Konrad Rudolph
              19 mins ago













            • 3




              Wow, them's some wonky scope rules.
              – Lightness Races in Orbit
              3 hours ago










            • It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
              – habnabit
              2 hours ago






            • 1




              @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
              – Giacomo Alzetta
              1 hour ago






            • 1




              It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
              – Shamtam
              52 mins ago







            • 2




              @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
              – Konrad Rudolph
              19 mins ago








            3




            3




            Wow, them's some wonky scope rules.
            – Lightness Races in Orbit
            3 hours ago




            Wow, them's some wonky scope rules.
            – Lightness Races in Orbit
            3 hours ago












            It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
            – habnabit
            2 hours ago




            It's much simpler to use weakref.ref to demonstrate this; __del__ has confusing semantics which vary between runtimes and python versions.
            – habnabit
            2 hours ago




            1




            1




            @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
            – Giacomo Alzetta
            1 hour ago




            @LightnessRacesinOrbit Yeah, this is definitely strange. I mean: if you want a new scope then create a new scope and don't kill the reference to the first msg. If you don't want a new scope, then why kill the exception reference?
            – Giacomo Alzetta
            1 hour ago




            1




            1




            It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
            – Shamtam
            52 mins ago





            It's not wonky at all. By using except ... as msg you're binding msg to the exception, which removes all references to the original object. Conversely, if except ... as m was used, it wouldn't result in any issue since the original binding msg isn't modified in the except block.
            – Shamtam
            52 mins ago





            2




            2




            @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
            – Konrad Rudolph
            19 mins ago





            @Shamtam As Giacomo explains, it’s definitely wonky. The way Python works, it rebinds msg in the existing scope. But the scope of msg exists beyond the try block (and would continue to, if no exception were raised). The fact that a runtime condition determines the scope of a variable (which should be static) is a crass subversion of the type system. Since Python is dynamically typed this of course works but it’s nevertheless weird. What’s more, Python 2 handles this completely differently, and as expected.
            – Konrad Rudolph
            19 mins ago













            up vote
            11
            down vote













            msg in the except clause is in the same scope as msg on the first line.



            But in Python 3 we have this new behavior too:




            When an exception has been assigned using as target, it is cleared at
            the end of the except clause. This is as if



            except E as N:
            foo


            was translated to



            except E as N:
            try:
            foo
            finally:
            del N



            so, you "overwrite msg" in the exception handler, and exiting the handler will delete the variable.






            share|improve this answer


















            • 1




              This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
              – Jeronimo
              2 hours ago















            up vote
            11
            down vote













            msg in the except clause is in the same scope as msg on the first line.



            But in Python 3 we have this new behavior too:




            When an exception has been assigned using as target, it is cleared at
            the end of the except clause. This is as if



            except E as N:
            foo


            was translated to



            except E as N:
            try:
            foo
            finally:
            del N



            so, you "overwrite msg" in the exception handler, and exiting the handler will delete the variable.






            share|improve this answer


















            • 1




              This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
              – Jeronimo
              2 hours ago













            up vote
            11
            down vote










            up vote
            11
            down vote









            msg in the except clause is in the same scope as msg on the first line.



            But in Python 3 we have this new behavior too:




            When an exception has been assigned using as target, it is cleared at
            the end of the except clause. This is as if



            except E as N:
            foo


            was translated to



            except E as N:
            try:
            foo
            finally:
            del N



            so, you "overwrite msg" in the exception handler, and exiting the handler will delete the variable.






            share|improve this answer














            msg in the except clause is in the same scope as msg on the first line.



            But in Python 3 we have this new behavior too:




            When an exception has been assigned using as target, it is cleared at
            the end of the except clause. This is as if



            except E as N:
            foo


            was translated to



            except E as N:
            try:
            foo
            finally:
            del N



            so, you "overwrite msg" in the exception handler, and exiting the handler will delete the variable.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited 17 mins ago









            Konrad Rudolph

            389k1007641015




            389k1007641015










            answered 3 hours ago









            Uku Loskit

            28.4k76578




            28.4k76578







            • 1




              This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
              – Jeronimo
              2 hours ago













            • 1




              This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
              – Jeronimo
              2 hours ago








            1




            1




            This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
            – Jeronimo
            2 hours ago





            This answers specifically the question how and why the previous msg gets deleted after the except:, including reference to the docs, so IMHO it should be the accepted answer.
            – Jeronimo
            2 hours ago











            up vote
            2
            down vote













            Exception blocks delete the caught variable at the end of the block, but they do not have their own scopes. So the sequence of events goes:



            1) msg is set to some string in the local scope



            2) msg is set to an IndexError object in the same local scope as 1



            3) msg is deleted from the local scope when the Exception block ends



            4) msg is no longer defined in the local scope, so the attempt to access it fails






            share|improve this answer








            New contributor




            Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.





















              up vote
              2
              down vote













              Exception blocks delete the caught variable at the end of the block, but they do not have their own scopes. So the sequence of events goes:



              1) msg is set to some string in the local scope



              2) msg is set to an IndexError object in the same local scope as 1



              3) msg is deleted from the local scope when the Exception block ends



              4) msg is no longer defined in the local scope, so the attempt to access it fails






              share|improve this answer








              New contributor




              Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
              Check out our Code of Conduct.



















                up vote
                2
                down vote










                up vote
                2
                down vote









                Exception blocks delete the caught variable at the end of the block, but they do not have their own scopes. So the sequence of events goes:



                1) msg is set to some string in the local scope



                2) msg is set to an IndexError object in the same local scope as 1



                3) msg is deleted from the local scope when the Exception block ends



                4) msg is no longer defined in the local scope, so the attempt to access it fails






                share|improve this answer








                New contributor




                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.









                Exception blocks delete the caught variable at the end of the block, but they do not have their own scopes. So the sequence of events goes:



                1) msg is set to some string in the local scope



                2) msg is set to an IndexError object in the same local scope as 1



                3) msg is deleted from the local scope when the Exception block ends



                4) msg is no longer defined in the local scope, so the attempt to access it fails







                share|improve this answer








                New contributor




                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.









                share|improve this answer



                share|improve this answer






                New contributor




                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.









                answered 3 hours ago









                Michael

                412




                412




                New contributor




                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.





                New contributor





                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.






                Michael is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.




















                    up vote
                    -4
                    down vote













                    because indentation matters. you were running msg outside of that try/except local scope



                    msg = "test"
                    try:
                    "a"[1]
                    except IndexError as msg:
                    print("Error happened")
                    print(msg)


                    as per @Lightness Races in Orbit suggestion, here's how i'd rephrase my answer:



                    when msg is cast/pointed as IndexError, it overloaded old msg, thus only lives within try/except scope.

                    local scope here means relative to try/except, not '__main__', where the old msg = 'test' lives together with try/except. proof is in the code up there.






                    share|improve this answer






















                    • msg existed already before that scope, so that's not the problem.
                      – Jeronimo
                      3 hours ago










                    • except IndexError as msg: overloaded msg
                      – cryptonome
                      3 hours ago










                    • No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                      – Lightness Races in Orbit
                      3 hours ago











                    • @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                      – cryptonome
                      3 hours ago











                    • @cryptonome try-except doesn't introduce a new scope.
                      – habnabit
                      2 hours ago














                    up vote
                    -4
                    down vote













                    because indentation matters. you were running msg outside of that try/except local scope



                    msg = "test"
                    try:
                    "a"[1]
                    except IndexError as msg:
                    print("Error happened")
                    print(msg)


                    as per @Lightness Races in Orbit suggestion, here's how i'd rephrase my answer:



                    when msg is cast/pointed as IndexError, it overloaded old msg, thus only lives within try/except scope.

                    local scope here means relative to try/except, not '__main__', where the old msg = 'test' lives together with try/except. proof is in the code up there.






                    share|improve this answer






















                    • msg existed already before that scope, so that's not the problem.
                      – Jeronimo
                      3 hours ago










                    • except IndexError as msg: overloaded msg
                      – cryptonome
                      3 hours ago










                    • No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                      – Lightness Races in Orbit
                      3 hours ago











                    • @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                      – cryptonome
                      3 hours ago











                    • @cryptonome try-except doesn't introduce a new scope.
                      – habnabit
                      2 hours ago












                    up vote
                    -4
                    down vote










                    up vote
                    -4
                    down vote









                    because indentation matters. you were running msg outside of that try/except local scope



                    msg = "test"
                    try:
                    "a"[1]
                    except IndexError as msg:
                    print("Error happened")
                    print(msg)


                    as per @Lightness Races in Orbit suggestion, here's how i'd rephrase my answer:



                    when msg is cast/pointed as IndexError, it overloaded old msg, thus only lives within try/except scope.

                    local scope here means relative to try/except, not '__main__', where the old msg = 'test' lives together with try/except. proof is in the code up there.






                    share|improve this answer














                    because indentation matters. you were running msg outside of that try/except local scope



                    msg = "test"
                    try:
                    "a"[1]
                    except IndexError as msg:
                    print("Error happened")
                    print(msg)


                    as per @Lightness Races in Orbit suggestion, here's how i'd rephrase my answer:



                    when msg is cast/pointed as IndexError, it overloaded old msg, thus only lives within try/except scope.

                    local scope here means relative to try/except, not '__main__', where the old msg = 'test' lives together with try/except. proof is in the code up there.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited 1 hour ago

























                    answered 3 hours ago









                    cryptonome

                    575114




                    575114











                    • msg existed already before that scope, so that's not the problem.
                      – Jeronimo
                      3 hours ago










                    • except IndexError as msg: overloaded msg
                      – cryptonome
                      3 hours ago










                    • No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                      – Lightness Races in Orbit
                      3 hours ago











                    • @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                      – cryptonome
                      3 hours ago











                    • @cryptonome try-except doesn't introduce a new scope.
                      – habnabit
                      2 hours ago
















                    • msg existed already before that scope, so that's not the problem.
                      – Jeronimo
                      3 hours ago










                    • except IndexError as msg: overloaded msg
                      – cryptonome
                      3 hours ago










                    • No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                      – Lightness Races in Orbit
                      3 hours ago











                    • @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                      – cryptonome
                      3 hours ago











                    • @cryptonome try-except doesn't introduce a new scope.
                      – habnabit
                      2 hours ago















                    msg existed already before that scope, so that's not the problem.
                    – Jeronimo
                    3 hours ago




                    msg existed already before that scope, so that's not the problem.
                    – Jeronimo
                    3 hours ago












                    except IndexError as msg: overloaded msg
                    – cryptonome
                    3 hours ago




                    except IndexError as msg: overloaded msg
                    – cryptonome
                    3 hours ago












                    No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                    – Lightness Races in Orbit
                    3 hours ago





                    No, this is exactly the crux of the question: OP expected the original msg from the outer "scope" (which, it turns out, is the same as the inner scope actually) to be available still. They're not trying to get the IndexError.
                    – Lightness Races in Orbit
                    3 hours ago













                    @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                    – cryptonome
                    3 hours ago





                    @LightnessRacesinOrbit once msg is defined to be used for try/except (that is declared within the same scope as the original msg = 'test), msg lives within try/except local scope. with that block exited, msg no longer points to anything so the pointer's also removed after that block is finished. how is that false?
                    – cryptonome
                    3 hours ago













                    @cryptonome try-except doesn't introduce a new scope.
                    – habnabit
                    2 hours ago




                    @cryptonome try-except doesn't introduce a new scope.
                    – habnabit
                    2 hours ago

















                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52965952%2fexcept-foo-as-bar-causes-bar-to-be-removed-from-scope%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Comments

                    Popular posts from this blog

                    What does second last employer means? [closed]

                    List of Gilmore Girls characters

                    Confectionery