• Login
Community
  • Login

Pythonscript show console on error

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
38 Posts 3 Posters 26.4k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C
    Claudia Frank @Alan Kilborn
    last edited by Feb 12, 2017, 11:04 PM

    @Alan-Kilborn

    ok - tried to understand the python script source code and this is what I assume is
    what happens.

    When executing python files, the one we create with Plugins->PythonScript-New Script
    code.py is NOT used, instead the C++ implementation of the python interface,
    namely PyRun_Simplefile. Makes a lot of sense.

    When executing code in the console then code.py is used. (Not interesting for this issue)

    Because of this, there is no need to change code.py but to make a global execption hook
    working we have to put the following code into one of the startup.py files.
    I prefer user startup.py but machine startup.py will work too.

    import sys
    
    def my_logging_func(exctype, value, traceback):
        console.show()
        console.write('{}\n{}\n{}\n'.format(exctype, value, traceback))
    
    sys.excepthook = my_logging_func
    

    Of course the my_logging_func code could look different for each.
    But the parameters need to be 3!

    When does it fail?
    Python interpreter tries to compile the source before it gets executed and that means
    if an exception is raised while compiling the source which includes the exception hook,
    the hook cannot be installed.

    Concerning the console.show() freeze, I’m using the console.show() since I started
    with python script. I also tried your example it is working for me.

    When your npp hangs than it means that python script created a deadlock.
    But what could be the cause when running console.show()?
    Can you run console.hide() when you open the console manually (via menu)?
    Is there something special in your startup.pys?

    Cheers
    Claudia

    1 Reply Last reply Reply Quote 1
    • C
      Claudia Frank @Alan Kilborn
      last edited by Feb 12, 2017, 11:36 PM

      @Alan-Kilborn

      came just into my mind - could it be that you are using callbacks in your
      startup.py files which could jump in?

      Cheers
      Claudia

      A 1 Reply Last reply Feb 13, 2017, 1:20 AM Reply Quote 1
      • A
        Alan Kilborn @Claudia Frank
        last edited by Feb 13, 2017, 1:20 AM

        @Claudia-Frank

        Okay, I disabled code initiated from startup.py that had a callback associated with it, and…everything (the “my_logging_func” stuff, and the “try/main()” stuff) discussed above now works. So the question becomes, what do the callbacks have to do with anything, as long as the callbacks don’t contain any code with unhandled exceptions?

        And then the next question is, how do I get it all…my code with callbacks, and a custom exception handler (which does the console.show() )?

        And again, Claudia, thank you for your diligence!

        C 1 Reply Last reply Feb 13, 2017, 8:52 AM Reply Quote 0
        • C
          Claudia Frank @Alan Kilborn
          last edited by Feb 13, 2017, 8:52 AM

          @Alan-Kilborn

          Just a quick update - the exception hook should work together with your callbacks,
          opening the console is the problem. If you want to know more about this there must
          be an old thread at sourceforge forum.
          To overcome this, use notepad.runPluginCommand(‘Python Script’, ‘Show Console’)
          instead of console.show() (Please double check syntax)

          Cheers
          Claudia

          A 1 Reply Last reply Feb 13, 2017, 1:04 PM Reply Quote 1
          • A
            Alan Kilborn @Claudia Frank
            last edited by Feb 13, 2017, 1:04 PM

            @Claudia-Frank

            I found this at sourceforge. It doesn’t really detail anything, but it reminds me of our current discussion!
            https://sourceforge.net/p/npppythonscript/discussion/1188885/thread/a1ec71f7/?limit=25#c261

            C 1 Reply Last reply Feb 13, 2017, 11:32 PM Reply Quote 0
            • A
              Alan Kilborn
              last edited by Feb 13, 2017, 3:52 PM

              So here’s what I ended up embedding in startup.py…seems to do the job and meet the original requirement:

              import traceback
              def custom_exception_handler_func(exctype, value, trace_back):
                  notepad.runPluginCommand('Python Script', 'Show Console')  # can't/don't use console.show()
                  sys.stderr.write('(Single-level) Traceback:' + '\n')
                  sys.stderr.write(traceback.format_tb(trace_back)[-1])  # only write out ONE level
              sys.excepthook = custom_exception_handler_func
              
              1 Reply Last reply Reply Quote 1
              • C
                Claudia Frank @Alan Kilborn
                last edited by Feb 13, 2017, 11:32 PM

                @Alan-Kilborn

                I found this at sourceforge. It doesn’t really detail anything, but it reminds me of our current discussion!
                https://sourceforge.net/p/npppythonscript/discussion/1188885/thread/a1ec71f7/?limit=25#c261

                No, I have something in my mind related to the problems using console object
                together with editor callbacks. Did a quick search but wasn’t able to find it.

                Anyway, good to see that you have a working solution and I hope you don’t open
                new python script related threads in the near future. Don’t get me wrong,
                but it looks like have a knack to find all those nasty issues ;-)

                Cheers
                Claudia

                A 1 Reply Last reply Feb 14, 2017, 12:23 AM Reply Quote 0
                • A
                  Alan Kilborn @Claudia Frank
                  last edited by Feb 14, 2017, 12:23 AM

                  @Claudia-Frank

                  Again, many thanks for your support. And I have no more “toughies” in the queue for you…but…when I do I know where (and who) to go to! :-)

                  Also, my most recent example lacks an “import sys” to be complete…

                  1 Reply Last reply Reply Quote 0
                  • D
                    DaveyD
                    last edited by Feb 14, 2017, 4:56 AM

                    @Claudia-Frank and @Alan-Kilborn,
                    Thanks for this thread - this is a nice feature that I’ve wanted for a while - now I have it! Thanks.

                    Regarding the console.show() crashing np++, I’ve had this issue before and it was also connected to a callback. See here and here.
                    At the time, Dave fixed it for us and it’s been working since.
                    Maybe those threads can give some clues…

                    Regards,
                    David

                    C 1 Reply Last reply Feb 14, 2017, 5:06 AM Reply Quote 1
                    • C
                      Claudia Frank @DaveyD
                      last edited by Feb 14, 2017, 5:06 AM

                      @DaveyD

                      David, thx - that is exactly the thread (second link) I was looking for.
                      Totally forgot (or didn’t even see) that there is an unofficial python script 1.1.1 .
                      But downloading and installing seems to confirm, the console object is working on
                      my side as well now.

                      Cheers
                      Claudia

                      A 1 Reply Last reply Feb 14, 2017, 3:28 PM Reply Quote 1
                      • A
                        Alan Kilborn @Claudia Frank
                        last edited by Feb 14, 2017, 3:28 PM

                        @Claudia-Frank

                        Is Pythonscript 1.1.1 something you are moving forward with for all of your PS development…or were you just doing a quick test in a sandbox install?

                        C 1 Reply Last reply Feb 14, 2017, 3:44 PM Reply Quote 0
                        • C
                          Claudia Frank @Alan Kilborn
                          last edited by Feb 14, 2017, 3:44 PM

                          @Alan-Kilborn

                          was just a quick test - I stay with the official 1.0.8.

                          Cheers
                          Claudia

                          1 Reply Last reply Reply Quote 0
                          • A
                            Alan Kilborn
                            last edited by Feb 15, 2017, 1:04 PM

                            Some additional time with the exception handler in place has shown the need for some tweaks to the code. Passing it along:

                            # set new exception hook so that when unhandled exception occurs while running a script,
                            #  it will force the Pythonscript console window to be shown
                            import sys, traceback
                            def custom_exception_handler_func(exctype, value, trace_back):
                                notepad.runPluginCommand('Python Script', 'Show Console')  # can't/don't use console.show() in PS 1.0.8.0
                                sys.stderr.write('(Single-level) Traceback:' + '\n')
                                sys.stderr.write(traceback.format_tb(trace_back)[-1])  # only write out ONE level
                                sys.stderr.write(str(exctype) + ':  ' + str(value) + '\n')
                            sys.excepthook = custom_exception_handler_func
                            
                            C 1 Reply Last reply Feb 15, 2017, 4:51 PM Reply Quote 0
                            • C
                              Claudia Frank @Alan Kilborn
                              last edited by Feb 15, 2017, 4:51 PM

                              @Alan-Kilborn

                              one of the features of the console I really like is the ability to click on a link
                              and the source file opens with the cursor at the position of the possible error.
                              For example, if you execute the following in the console

                              print '  File "{}", line {}'.format(notepad.getCurrentFilename(), 6)
                              

                              open another tab and then click on the link created in the console,
                              the file gets opened and the cursor is put on line 6.

                              If you check the value parameter of the hook function, you will see it is a tuple containing all the needed infos - maybe worth investigating.

                              Cheers
                              Claudia

                              A 1 Reply Last reply Feb 15, 2017, 6:38 PM Reply Quote 0
                              • A
                                Alan Kilborn @Claudia Frank
                                last edited by Feb 15, 2017, 6:38 PM

                                @Claudia-Frank said:

                                one of the features of the console I really like is the ability to click on a link
                                and the source file opens with the cursor at the position of the possible error.

                                Without changing any code from my most recent (above), if I create a single-line Pythonscript called t.py and put in it: z=zzzzz, then I run it with the new exception handler in place, I get this in the console:

                                (Single-level) Traceback:
                                  File "C:\Utilities\npp.bin\plugins\Config\PythonScript\scripts\t.py", line 1, in <module>
                                    z=zzzzz
                                <type 'exceptions.NameError'>:  name 'zzzzz' is not defined
                                >>> 
                                

                                where the filename in double-quotes is a clickable link which takes me to the file and line number indicated. Thus, while you have a great point, @Claudia-Frank , I really don’t have to do my own formatting like you describe to make it happen. :)

                                C 1 Reply Last reply Feb 15, 2017, 7:17 PM Reply Quote 0
                                • C
                                  Claudia Frank @Alan Kilborn
                                  last edited by Feb 15, 2017, 7:17 PM

                                  @Alan-Kilborn

                                  but only as long as the exception happens within the main script.
                                  If it happens in an imported module or script gets executed via another script,
                                  than it won’t work because of the restriction of your levels
                                  but the info is still kept in the value parameter.

                                  Cheers
                                  Claudia

                                  A 1 Reply Last reply Feb 15, 2017, 8:00 PM Reply Quote 0
                                  • A
                                    Alan Kilborn @Claudia Frank
                                    last edited by Feb 15, 2017, 8:00 PM

                                    @Claudia-Frank

                                    I know how to get upvotes – ask people to upvote if tired of this thread! :)

                                    Yea, okay, so I was trying to limit the amount of lines in the traceback, because usually it isn’t all that helpful. However, given what you said, I went in search of different scenarios, and I rapidly found 3, which all produce very different tracebacks, from which a pattern did not emerge on how to reduce the amount of levels. The 3 scenarios I found were as follows:

                                    z=zzzz
                                    m = re.search('(', 'abc')
                                        x=3
                                    

                                    Comment out any two of these script lines at a time, run it and observe a full traceback and note how different they are (if you were to consider coding something to only let certain traceback levels be shown – pretty complicated).

                                    So I’ve decided the best thing is to let all of the levels be shown. My latest (and hopefully last) version of this little custom exception hook, hopefully of value to some that DON’T decide to upvote :-) is:

                                    import sys, traceback
                                    def custom_exception_handler_func(exctype, value, trace_back):
                                        notepad.runPluginCommand('Python Script', 'Show Console')  # can't/don't use console.show() in PS 1.0.8.0
                                        sys.stderr.write('Traceback:' + '\n')
                                        for tb in traceback.format_tb(trace_back): sys.stderr.write(tb)
                                        sys.stderr.write(str(exctype) + ':  ' + str(value) + '\n')
                                    sys.excepthook = custom_exception_handler_func
                                    
                                    C 1 Reply Last reply Jul 18, 2017, 8:47 PM Reply Quote 0
                                    • C
                                      Claudia Frank @Alan Kilborn
                                      last edited by Claudia Frank Jul 18, 2017, 8:48 PM Jul 18, 2017, 8:47 PM

                                      @Alan-Kilborn

                                      Hi Alan, I totally forgot about this one and I have found another way to do it.
                                      A more python script plugin way.

                                      There is a class ConsoleError defined in machine startup.py which we can enhance.

                                      class ConsoleError:
                                          def __init__(self):
                                              global console
                                              self._console = console;
                                              
                                          def write(self, text):
                                              notepad.runPluginCommand('Python Script', 'Show Console')
                                              self._console.writeError(text);
                                              
                                      sys.stderr = ConsoleError()
                                      

                                      and in addition, it we want to get every print statement behave the same,
                                      we can introduce a similar class for stdout

                                      class ConsoleStdOut:
                                          def __init__(self):
                                              global console
                                              self._console = console;
                                              
                                          def write(self, text):
                                              notepad.runPluginCommand('Python Script', 'Show Console')
                                              self._console.write(text);
                                              
                                      sys.stdout = ConsoleStdOut()
                                      

                                      Done. :-)

                                      Cheers
                                      Claudia

                                      A 1 Reply Last reply Jul 19, 2017, 12:57 PM Reply Quote 1
                                      • A
                                        Alan Kilborn @Claudia Frank
                                        last edited by Jul 19, 2017, 12:57 PM

                                        @Claudia-Frank

                                        I tried this out and now my print statements in scripts will show the PS console if it is not currently showing. This is helpful. Thank you.

                                        However, I noticed that, regardless of whether or not the PS console is showing when the print statement is encountered, after the script finishes the PS console has the input focus. This situation is OK if an exception in the script occurs, but for simple print statements I’d rather keep the focus where I’m editing.

                                        Perhaps to solve this one would have to use a variation of the “grandpa” technique shown here, but changing it to simply put input focus back on the current editor tab? Sadly, maybe I see the solution but do not have the power to implement it. :-)

                                        C 1 Reply Last reply Jul 19, 2017, 1:12 PM Reply Quote 0
                                        • C
                                          Claudia Frank @Alan Kilborn
                                          last edited by Jul 19, 2017, 1:12 PM

                                          @Alan-Kilborn

                                          We should stress grandpa too much :-D
                                          Add

                                          notepad.activateBufferID(notepad.getCurrentBufferID())
                                          

                                          after the write call.

                                          Cheers
                                          Claudia

                                          1 Reply Last reply Reply Quote 1
                                          • First post
                                            Last post
                                          The Community of users of the Notepad++ text editor.
                                          Powered by NodeBB | Contributors