How to get a raised exception from other thread

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • dcrespo

    How to get a raised exception from other thread

    Hi all,

    How can I get a raised exception from other thread that is in an
    imported module?

    For example:

    ---------------
    programA.py
    ---------------

    import programB

    thread = programB.MakeTh read()
    thread.start()

    ---------------
    programB.py
    ---------------
    import threading, time

    class SomeException(E xception):
    pass

    class MakeThread(thre ading.Thread):
    def __init__(self):
    threading.Threa d.__init__(self )

    def run(self):
    i = 0
    while 1:
    print i
    i += 1
    time.sleep(1) #wait a second to continue
    if i>10:
    raise SomeException()


    Thanks

    Daniel

  • Jeremy Moles

    #2
    Re: How to get a raised exception from other thread

    On non-Windows system there are a ton of ways to do it--this is almost a
    whole field unto itself. :) (D-BUS, fifos, sockets, shmfs, etc.) In
    Windows, I wouldn't have a clue.

    I guess this is a hard question to answer without a bit more
    information. :)

    On Fri, 2005-10-14 at 14:45 -0700, dcrespo wrote:[color=blue]
    > Hi all,
    >
    > How can I get a raised exception from other thread that is in an
    > imported module?
    >
    > For example:
    >
    > ---------------
    > programA.py
    > ---------------
    >
    > import programB
    >
    > thread = programB.MakeTh read()
    > thread.start()
    >
    > ---------------
    > programB.py
    > ---------------
    > import threading, time
    >
    > class SomeException(E xception):
    > pass
    >
    > class MakeThread(thre ading.Thread):
    > def __init__(self):
    > threading.Threa d.__init__(self )
    >
    > def run(self):
    > i = 0
    > while 1:
    > print i
    > i += 1
    > time.sleep(1) #wait a second to continue
    > if i>10:
    > raise SomeException()
    >
    >
    > Thanks
    >
    > Daniel
    >[/color]

    Comment

    • dcrespo

      #3
      Re: How to get a raised exception from other thread

      Thanks for your answer, but I think that created thread in python
      should create a thread either on windows and linux.

      Can you give me Python example of how to do what I want to do? Thanks

      Comment

      • Peter Hansen

        #4
        Re: How to get a raised exception from other thread

        dcrespo wrote:[color=blue]
        > How can I get a raised exception from other thread that is in an
        > imported module?[/color]

        Define what "get" means for your purposes. It appears that you mean you
        want to catch the exception, but in the thread which launched the other
        thread in the first place. If that's true, please show where you would
        expect to catch this exception, given that when you start the thread,
        the main thread continues running and might even finish before the other
        thread finishes.
        [color=blue]
        > thread = programB.MakeTh read()
        > thread.start()[/color]
        ....
        # later code which might have completed by the time the thread finishes
        ....

        Are you looking, for example, for some kind of
        thread.waitUnti lCompletionAndR eRaiseException s() method?

        -Peter

        Comment

        • themightydoyle@gmail.com

          #5
          Re: How to get a raised exception from other thread

          I also need an answer to this problem. I'm using windows. Throwing an
          exception in thread B from thread A using a callback function.

          The function runs, but the thread never actually catches the exception.
          The try/except block is in the run() method (over-riden from the
          Thread class)

          Comment

          • Peter Hansen

            #6
            Re: How to get a raised exception from other thread

            themightydoyle@ gmail.com wrote:[color=blue]
            > I also need an answer to this problem.[/color]

            What _is_ the problem? We're still waiting for a clear description from
            the OP as to what the problem really is. How would you describe what
            _your_ problem is?
            [color=blue]
            > I'm using windows. Throwing an
            > exception in thread B from thread A using a callback function.
            >
            > The function runs, but the thread never actually catches the exception.
            > The try/except block is in the run() method (over-riden from the
            > Thread class)[/color]

            Rather than force us all to guess what you are doing wrong, maybe it
            would be better if you posted a small amount of code that shows the problem.

            Exceptions raised in threads can definitely be caught in the run()
            method if the code is written correctly, so that is not in itself an issue.

            -Peter

            Comment

            • themightydoyle@gmail.com

              #7
              Re: How to get a raised exception from other thread

              Here's a dumbed down version of what i'm doing:

              import time
              import threading

              class threader(thread ing.Thread):
              def __init__(self):
              threading.Threa d.__init__(self )
              pass

              def run(self):
              try:
              while 1:
              time.sleep(5)
              except SystemExit:
              print "Got Exit Message in thread"

              def killMe(self):
              raise SystemExit



              thread1 = threader()
              thread2 = threader()

              thread1.start()
              thread2.start()

              time.sleep(5)

              try:
              print "Killing thread 1"
              thread1.killMe( )
              print "killing thread 2"
              thread2.killMe( )
              except SystemExit:
              print "Got exceptin in main thread"



              The exception is not propogated to the threads I spawned, but instead
              comes back in the main thread.

              Comment

              • themightydoyle@gmail.com

                #8
                Re: How to get a raised exception from other thread

                Nevermind. I found a better solution. I used shared memory to create
                a keep-alive flag. I then use the select function with a specified
                timeout, and recheck the keep-alive flag after each timeout.

                Thanx for all the input.

                Comment

                • Dennis Lee Bieber

                  #9
                  Re: How to get a raised exception from other thread

                  On 15 Oct 2005 20:54:33 -0700, themightydoyle@ gmail.com declaimed the
                  following in comp.lang.pytho n:

                  [color=blue]
                  > try:
                  > print "Killing thread 1"
                  > thread1.killMe( )
                  > print "killing thread 2"
                  > thread2.killMe( )
                  > except SystemExit:
                  > print "Got exceptin in main thread"
                  >
                  >
                  >
                  > The exception is not propogated to the threads I spawned, but instead
                  > comes back in the main thread.[/color]

                  No surprise there... The function invocation is being made in the
                  CONTEXT of the main thread...
                  --[color=blue]
                  > =============== =============== =============== =============== == <
                  > wlfraed@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
                  > wulfraed@dm.net | Bestiaria Support Staff <
                  > =============== =============== =============== =============== == <
                  > Home Page: <http://www.dm.net/~wulfraed/> <
                  > Overflow Page: <http://wlfraed.home.ne tcom.com/> <[/color]

                  Comment

                  • Klaas

                    #10
                    Re: How to get a raised exception from other thread

                    In article <1129438147.182 266.196790@g44g 2000cwa.googleg roups.com>,
                    themightydoyle@ gmail.com wrote:
                    [color=blue]
                    > Nevermind. I found a better solution. I used shared memory to create
                    > a keep-alive flag. I then use the select function with a specified
                    > timeout, and recheck the keep-alive flag after each timeout.
                    >
                    > Thanx for all the input.[/color]

                    How about a threading.Event ?

                    -Mike

                    Comment

                    • Peter Hansen

                      #11
                      Re: How to get a raised exception from other thread

                      themightydoyle@ gmail.com wrote:[color=blue]
                      > Nevermind. I found a better solution. I used shared memory to create
                      > a keep-alive flag. I then use the select function with a specified
                      > timeout, and recheck the keep-alive flag after each timeout.[/color]

                      As Dennis points out, your original attempt was destined to fail because
                      you were calling the method from the main thread, not the one you wanted
                      to kill. Threads don't magically execute any methods that are attached
                      to the Thread instance just because they're attached. You have to
                      actually call those methods *from* the thread, which means from the
                      run() method or from any of the routines it calls (whether they are
                      methods on that Thread or not), but it must be done in the context of
                      the thread you want to raise exceptions in or it won't work.

                      More importantly, you've now described your use case (and I hope that of
                      the OP as well, since he hasn't replied yet): killing threads.

                      This is an oft-discussed topic here, and searching the archives will
                      probably give you lots more answers, but the short answer is you cannot
                      kill a thread in Python (except by exiting the entire process). Instead,
                      as you've discovered, you must ask it nicely to exit. The nearly
                      canonical approach to doing that is as follows:

                      class MyThread(thread ing.Thread):
                      def __init__(self, *args, **kwargs):
                      threading.Threa d.__init__(self , *args, **kwargs)
                      self._keepRunni ng = True

                      def stop(self, timeout=None):
                      self._keepRunni ng = False
                      # optional: wait for thread to exit
                      self.join(timeo ut=timeout)

                      def run(self):
                      while self._keepRunni ng:
                      # do stuff here

                      Now you can do things like this:

                      thread = MyThread()
                      thread.start()
                      # other stuff...
                      thread.stop() # block here until the thread exits

                      I hope that clarifies things a little more...

                      -Peter

                      Comment

                      • Lasse Vågsæther Karlsen

                        #12
                        Re: How to get a raised exception from other thread

                        Peter Hansen wrote:[color=blue]
                        > themightydoyle@ gmail.com wrote:
                        >[color=green]
                        >> Nevermind. I found a better solution. I used shared memory to create
                        >> a keep-alive flag. I then use the select function with a specified
                        >> timeout, and recheck the keep-alive flag after each timeout.[/color]
                        >
                        >
                        > As Dennis points out, your original attempt was destined to fail because
                        > you were calling the method from the main thread, not the one you wanted[/color]
                        <snip>

                        A similar problem exists in .NET but they "solved" it by creating an
                        Abort method that raises an exception in the thread itself, basically
                        doing what you wanted to do.

                        However, this leads to all sorts of problem, particular when that
                        exception is raised in a finally block in that thread, which could mean
                        that the finally block did not fully execute, leading to resource leaks
                        or similar problems.

                        They pondered a while about constructing non-interruptible blocks of
                        code for .NET 2.0 but I'm not entirely sure how that worked out.

                        In any case, the best way is to use some kind of signal that the thread
                        reacts to, either by having it specifically wait for a signallable
                        object (like an event) or just by checking a boolean variable or similar
                        for a magic value that means "now is a good time for you to terminate".

                        --
                        Lasse Vågsæther Karlsen

                        mailto:lasse@vk arlsen.no
                        PGP KeyID: 0x2A42A1C2

                        Comment

                        • Alex Martelli

                          #13
                          Re: How to get a raised exception from other thread

                          <themightydoyle @gmail.com> wrote:
                          [color=blue]
                          > Nevermind. I found a better solution. I used shared memory to create
                          > a keep-alive flag. I then use the select function with a specified
                          > timeout, and recheck the keep-alive flag after each timeout.[/color]

                          Definitely a better architecture. Anyway, one supported way for a
                          thread to raise an exception in a different thread is function
                          thread.interrup t_main(), which raises a KeyboardInterru pt in the *main*
                          thread (the one thread that's running at the beginning of your program).

                          There's also a supported, documented function to raise any given
                          exception in any existing thread, but it's deliberately NOT directly
                          exposed to Python code -- you need a few lines of C-coded extension (or
                          pyrex, ctypes, etc, etc) to get at the functionality. This small but
                          non-null amount of "attrition" was deliberately put there to avoid
                          casual overuse of a facility intended only to help in very peculiar
                          cases (essentially in debuggers &c, where the thread's code may be buggy
                          and fail to check a keep-alive flag correctly...!-).


                          Alex

                          Comment

                          • Antoon Pardon

                            #14
                            Re: How to get a raised exception from other thread

                            Op 2005-10-14, dcrespo schreef <dcrespo@gmail. com>:[color=blue]
                            > Hi all,
                            >
                            > How can I get a raised exception from other thread that is in an
                            > imported module?
                            >
                            > For example:[/color]

                            You could try the following class, it needs ctypes and if the exception
                            is raised while in a C-extention, the exception will be delayed until
                            the extention is left. Some delay is unavoidable. You may also need
                            to fiddle with the length of the sleep at the end of this script
                            or the values in the xrange calls in the Continue threads

                            ---------------------------- except.py --------------------------------

                            import os
                            import ctypes
                            from time import sleep
                            from random import randint


                            class TimeOut(Excepti on):
                            pass


                            class Alarm(Exception ):
                            pass

                            import threading

                            class Xthread(threadi ng.Thread):


                            def start(self):
                            self.__original _run = self.run
                            self.run = self.__run
                            threading.Threa d.start(self)


                            def __run(self):
                            self.__thrd_id = threading._get_ ident()
                            try:
                            self.__original _run()
                            finally:
                            self.run = self.__original _run


                            def raize(self, excpt):

                            Nr = ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf.__thrd_id, ctypes.py_objec t(excpt))
                            while Nr > 1:
                            ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf.__thrd_id, None)
                            sleep(0.1)
                            Nr = ctypes.pythonap i.PyThreadState _SetAsyncExc(se lf.__thrd_id, ctypes.py_objec t(excpt))

                            def alarm(self, tm):

                            alrm = threading.Timer (tm, self.raize, (TimeOut,))
                            alrm.start()
                            return alrm

                            class Continue(Xthrea d):

                            def run(self):

                            self.id = os.getpid()
                            print self.id, "Begin"
                            i = 0
                            try:
                            for _ in xrange(randint( 0,20)):
                            for e in xrange(4 * 100000):
                            i = i + e
                            print self.id, "Finished"
                            except Alarm:
                            print self.id, "Interupted "


                            lst = [Continue() for _ in xrange(10)]

                            for T in lst:
                            T.start()

                            try:
                            sleep(15)
                            finally:
                            for T in lst:
                            T.raize(Alarm)

                            Comment

                            • Antoon Pardon

                              #15
                              Re: How to get a raised exception from other thread

                              Op 2005-10-17, Alex Martelli schreef <aleaxit@yahoo. com>:[color=blue]
                              ><themightydoyl e@gmail.com> wrote:
                              >[color=green]
                              >> Nevermind. I found a better solution. I used shared memory to create
                              >> a keep-alive flag. I then use the select function with a specified
                              >> timeout, and recheck the keep-alive flag after each timeout.[/color]
                              >
                              > Definitely a better architecture. Anyway, one supported way for a
                              > thread to raise an exception in a different thread is function
                              > thread.interrup t_main(), which raises a KeyboardInterru pt in the *main*
                              > thread (the one thread that's running at the beginning of your program).
                              >
                              > There's also a supported, documented function to raise any given
                              > exception in any existing thread, but it's deliberately NOT directly
                              > exposed to Python code -- you need a few lines of C-coded extension (or
                              > pyrex, ctypes, etc, etc) to get at the functionality. This small but
                              > non-null amount of "attrition" was deliberately put there to avoid
                              > casual overuse of a facility intended only to help in very peculiar
                              > cases (essentially in debuggers &c, where the thread's code may be buggy
                              > and fail to check a keep-alive flag correctly...!-).[/color]

                              I find this rather arrogant. It is not up to the developers of python
                              to decide how the users of python will use the language. If someone
                              has use of specific functionality he shouldn't be stopped because his
                              use is outside the intentions of the developers.

                              Just suppose you are writing a chess program. You let the program
                              "think" while it is the users move, but this thinking has to be
                              interrupted and some cleanup has to be made after the users move
                              has made a lot of this thinking obsolete by his move. Such code
                              could be mixture of loops and recursion that makes use of a simple
                              flag to end it all, unpractical. Use of an exception raised from
                              somewhere else would IMO in this case be an acceptable choice.

                              Why should the coder of this software have to go through this
                              deliberate set up attrition, to get at this functionality, just
                              because it wasn't intented to be used in such a way by the
                              developers?

                              As far as I know, pyrex and ctypes weren't intended to get
                              at the Python/C api. But they didn't create extra hurdles
                              for those who could use it that way.

                              --
                              Antoon Pardon

                              Comment

                              Working...