Community
    • Login

    Pythonscript plugin: how to end the script but not quit Notepad++

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    13 Posts 4 Posters 2.0k 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.
    • Alan KilbornA
      Alan Kilborn @P Cooper
      last edited by

      @P-Cooper said in Pythonscript plugin: how to end the script but not quit Notepad++:

      I reckon this lack of a suitable command could prove annoying for large projects anyone wanted to do based on the plugin…

      You reckon wrongly.
      Any “large” effort would include “structuring” such that the solutions you call “indirect” are just, well, natural to do.

      I suppose everyone starts out doing PythonScript with all their statements slammed up against the left side (aka column 1):

      x=7
      if x==4:
          pass
      y=3
      

      etc.

      But I’d think/hope most people would “graduate” beyond that type of thing fairly quickly.

      BTW, the code snippet above puts x and y into the global namespace where they could possibly accidentally be resused in a bad way by other scripts. The “structure” that I’m talking about would prevent that.

      P CooperP 1 Reply Last reply Reply Quote 2
      • P CooperP
        P Cooper @Alan Kilborn
        last edited by P Cooper

        @Alan-Kilborn

        I believe that for much of the stuff done in PythonScript, especially by those otherwise unfamilar with Python, a ‘terminate script’ command would be useful and would save some effort, not meaning to say it’s best practice.

        Thanks for pointing out that those ‘wall-slammed’ variables aren’t local / temporary. I’ve now slammed

        variable = "" / = 0
        

        statements against the wall at the bottom of my scripts, hoping that will do the trick.

        Alan KilbornA 1 Reply Last reply Reply Quote 0
        • Alan KilbornA
          Alan Kilborn @P Cooper
          last edited by Alan Kilborn

          @P-Cooper said in Pythonscript plugin: how to end the script but not quit Notepad++:

          I believe that for much of the stuff done in PythonScript, especially by those otherwise unfamilar with Python, a ‘terminate script’ command would be useful

          Something people often don’t understand is that PythonScript is not a programming/scripting language. PythonScript is the plugin; the language is Python.

          Thus, the plugin can’t do anything that Python can’t do. For example, you’re asking for something that alters control flow. That’s like asking for PythonScript to offer a slightly different version of Python’s if or while keywords. It simply can’t be done.

          When you’re executing code with the plugin, you’re running Python. PythonScript gives you some extra objects that make working with Notepad++ easier (e.g. editor and notepad objects), but that’s the extent of it.

          All other the other “solutions” to the “problem” posed by this thread (found in the linked-to thread) work exactly the same way in pure Python.

          So I have advice for “those otherwise unfamilar with Python”, thinking that PythonScript is some lightweight (and simpler) thing… it’s not, so don’t think of it that way.

          One key way in which PythonScript’s Python IS different though, is that you can’t end it (its Python interpreter) without exiting Notepad++. With standalone Python, you execute it from a Cmd or PowerShell prompt with: python myscript.py. The program runs and control returns to the OS prompt. At that point myscript is gone from memory; its variables don’t “hang around” and can’t mess with the running of python my_second_script.py’s variables. Not so with PythonScript. Since under Notepad++, since the Python interpreter never stops running, variables with global scope remain in the namespace and can be used (if that’s the real intent) in subsequent scripts that are executed.


          I’ve now slammed
          …
          statements against the wall at the bottom of my scripts, hoping that will do the trick.

          Hmm, it won’t, but maybe I don’t fully understand what you mean… You can’t do a bunch of “hoping” and be successful with programming. :-)

          What I do when I’m PythonScripting, and what you’d need to do, to keep things like my x and y from global visibility, is to give them some localized scope.

          If people just want to “hack away” at Python/Notepad++, doing it the simple “slammed to the left” way is fine, but you can possibly open yourself up to some “strange” bugs sometimes.

          Even the simple construct shown before (to solve the problem originally posed):

          
          def main():
              x=7
              if x == 4:
                  return              # <-- this achieves the goal of a "quick exit the script"
              y=3
          
          main()
          

          protects you from this a good deal, because x and y now “belong” to main, so you can’t run into problems with other scripts that might use an (uninitialized) x and y (because those won’t exist in the global space). You’d have to refer to them as main.x and main.y for this to happen, which is much harder to do by accident. Well, unless you use main in every script, but even for that case, when you run the above script, it redefines main at every run, so you can’t possibly use an old main.x from another script.

          So, there are a ton of advantages to using the def main() / main() approach; maybe it is just difficult for noobs to get their head around it. I’d say “just do it”.

          There’s more to the story, and I’ve tried to keep it very simple and not always use totally correct terminology, just in an attempt of simple knowledge transfer…

          P CooperP Victorel PetrovichV 2 Replies Last reply Reply Quote 4
          • P CooperP
            P Cooper @Alan Kilborn
            last edited by P Cooper

            @Alan-Kilborn

            Thanks a lot for sharing your insights in detail.

            It was surprising (and seemed unnecessary) to me that quit() / exit() and sys.exit() all shut down Notepad++ rather than just terminate the script, and I thought maybe something could be done about that so that they could do what I had in mind, but as you point out that’s not possible in the Notepad++ environment. It strikes me as odd, though, that it’s not possible for the process to retain that kind of control over the script it’s running – can’t run it in a “new thread” or “sandbox-type thingy”, but I don’t have the foggiest idea about the internals.

            Well, this noob has finally gotten his head round the def main() / main() approach thanks to you and is now proudly using cleaner code!

            Alan KilbornA 1 Reply Last reply Reply Quote 3
            • Alan KilbornA
              Alan Kilborn @P Cooper
              last edited by Alan Kilborn

              @P-Cooper said in Pythonscript plugin: how to end the script but not quit Notepad++:

              sys.exit()

              Quite frankly, I was surprised the first time I encountered it, that sys.exit() will shut down Notepad++.

              However, sys.exit() in standalone Python is a really drastic way of ending a program, and, in practice, isn’t used much in real-world programming. I could go into detail, but perhaps a “trust me” on it will suffice.

              Since all of your PythonScripting efforts should be considered “real world” :-), “just don’t use sys.exit()” is the mantra good PS programmers should chant.

              P CooperP 1 Reply Last reply Reply Quote 2
              • P CooperP
                P Cooper @Alan Kilborn
                last edited by

                @Alan-Kilborn
                If I ever decide to dabble in Python proper, I’ll bear your advice in mind, thanks!

                Alan KilbornA 1 Reply Last reply Reply Quote 1
                • Alan KilbornA
                  Alan Kilborn @P Cooper
                  last edited by Alan Kilborn

                  @P-Cooper and everyone:

                  OK, so we’ve hinted a bit at structuring a PythonScript (thus far we’ve been doing it for purposes of easily exiting a running script).

                  So far, we’ve got this as a minimal technique:

                  def main():
                      x = 7
                      print('x:', x)
                      if x == 4: return  # <----- "terminate script" early
                      y = 3
                      print('y:', y)
                      # ...
                  
                  main()
                  

                  It works, no doubt about that. If you want to make a template out of it, just delete the demo junk and you’ll have:

                  def main():
                      # ...
                  
                  main()
                  

                  But, if you want to put a bit more “flair” on it, as well as set yourself up for more advanced script-writing in the future, consider this:

                  # -*- coding: utf-8 -*-
                  from __future__ import print_function
                  
                  # refs:
                  #  https://community.notepad-plus-plus.org/topic/24045
                  
                  from Npp import *
                  
                  #-------------------------------------------------------------------------------
                  
                  class XXXX(object):
                  
                      def __init__(self):
                          x = 7
                          print('x:', x)
                          if x == 4: return  # <----- "terminate script" early
                          y = 3
                          print('y:', y)
                          # ...
                  
                  #-------------------------------------------------------------------------------
                  
                  if __name__ == '__main__':
                      XXXX()
                  

                  Things to note:

                  • the from __future__ line is only needed if you intend to use “print” statements (for output onto the console) and you’re not using PythonScript 3.x
                  • nice refs: section so you can put info about where the script (or parts of it) originated
                  • the XXXX should be replaced with a nice “tag” for the script; when I’m doing it, if the name of my file is BarebonesBoilerplateDemo.py, then instead of XXXX, I use BBD, obviously the capital letter “acronym” of the filename (this is just the way I do it, you can totally go your own way here…)
                  • the “meat” of your script can go entirely in the __init__ function
                  • if you want/need some additional logical functions (encouraged!), you can certainly do that, like what is shown below:
                  # -*- coding: utf-8 -*-
                  from __future__ import print_function
                  
                  # refs:
                  #  https://community.notepad-plus-plus.org/topic/24045
                  
                  from Npp import *
                  
                  #-------------------------------------------------------------------------------
                  
                  class XXXX(object):
                  
                      def __init__(self):
                          x = 7
                          print('x:', x)
                          if x == 4: return  # <----- "terminate script" early
                          y = 3
                          print('y:', y)
                          # ...
                          self.my_function_1(x, y)
                          q = self.my_function_2(y)
                  
                      def my_function_1(self, a, b):
                          print('a:', a, 'b:', b)
                  
                      def my_function_2(self, z):
                          print('z:', z)
                          return z + 6
                  
                  #-------------------------------------------------------------------------------
                  
                  if __name__ == '__main__':
                      XXXX()
                  
                  1 Reply Last reply Reply Quote 3
                  • Alan KilbornA Alan Kilborn referenced this topic on
                  • Victorel PetrovichV Victorel Petrovich referenced this topic on
                  • Victorel PetrovichV
                    Victorel Petrovich @Alan Kilborn
                    last edited by Victorel Petrovich

                    @Alan-Kilborn said in Pythonscript plugin: how to end the script but not quit Notepad++:

                    because x and y now “belong” to main, so you can’t run into problems with other scripts that might use an (uninitialized) x and y (because those won’t exist in the global space). You’d have to refer to them as main.x and main.y for this to happen

                    From what I can tell, it’s impossible to access variables that way (main.x, gives error)… but then it’s even more to your point :)

                    I wonder whether you found advantages to wrapping in a class vs just using nested functions inside main() ?

                    No need to go in detail ; just curious whether you indeed found advantages or it’s just… a way that also works.

                    Mark OlsonM 1 Reply Last reply Reply Quote 0
                    • Mark OlsonM
                      Mark Olson @Victorel Petrovich
                      last edited by

                      @Victorel-Petrovich said in Pythonscript plugin: how to end the script but not quit Notepad++:

                      I wonder whether you found advantages to wrapping in a class vs just using nested functions inside main() ?

                      More advanced scripts can have multiple callbacks, and the result of one function can depend on the output of other functions.

                      Just a simple example (not going to bother writing the script, left as an exercise to the reader):

                      NOTIFICATION.BUFFERACTIVATED callback: save the current filename to a class variable
                      when the script is invoked: print(the current filename (saved by the callback))
                      
                      Victorel PetrovichV 1 Reply Last reply Reply Quote 0
                      • Victorel PetrovichV
                        Victorel Petrovich @Mark Olson
                        last edited by Victorel Petrovich

                        @Mark-Olson
                        Well, when I get to the point that functions won’t suffice, I’ll consider classes.

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