Python plugin - handling many scripts...
-
Hi, I had a few general questions about using the python plugin. I’ve been benefiting from it for a while now, and my script list keeps on growing more and more… and is getting a little too long.
Is there a way to handle this?
(I don’t mind so much the sub-script list, I am mostly speaking about the scripts that appear in the main python menu, in which many of my scripts appear, since only those that appear in this list can be used in shortcuts and in toolbar using Customize Toolbar plugin)Thanks
DaveyP.S. Just to mention a few ideas: In this regard, there a few ‘better’ options in the javascript plugin for n++:
- You can setup customized menus and submenus and have all your scripts listed within
- You can add a keyboard shortcut directly from the plugin, no need to go to settings > shortcut mapper
- All of the above can be done within one script (or multiple)
Are any of these options available through python plugin and I’m just missing it?
-
I would like to add one more part to the question,
Is it possible to run a python script from a python script?
This would also help, because then I can have a script that would raise an input box, and I can type in which script I wantI tried using
notepad.runPluginCommand("Python Script", "ScriptName")
but I got a message that another script is already running, which I assumed was the current one…So, Is this possible any other way?
Thanks
Davey -
For the running-a-pythonscript-file-from-another part of your question, have a look at the execfile() function.
-
Hi Scott, thanks for replying
I did not try this yet, but I do have a question:
I want the other_script_file to be run in n++ to make changes to the text. The execFile() is a python function, not a n++ function - does this work?Thanks,
Davey -
Should work. Try it out in some simple test first, before investing a lot of time architecting something bigger that could perhaps not work for your situation.
-
Hello Davey,
part1 - no, as you already said,
- main python script menu,
- toolbar (but no need of extra plugin)
- and context menu (with a level of one folder)
can be used to access scripts faster.
part2 - not really, Python Script plugin doesn’t allow execution of multiple scripts at the same time
but you can overcome this by using the python way - import might be your friend.Might, because you need to start writing the code a little bit different and you need to be aware
what import really means.When importing a python module, which isn’t really different to any other python script, the loader
executes every code which isn’t secured.I guess I better explain it by a simple example.
Assuming you have 2 python scripts
- main_test.py
- test1.py
The main_test.py is, as the name suggest ;-), the script which you use to execute other scripts
therefore it has the following line in it.import test1
test1.py scripts does have the lines
from Npp import * console.write('test1.py\n')
now if you execute main_test.py you will see that python script console shows test1.py as message.
So what you need to do to secure it, you need to take care that every code is encapsulated in a function.from Npp import * def main(): console.write('test1.py\n')
Now you can import it from main_test and nothing gets executed automatically.
Run an inputbox, choose the script you want and execute it liketest1.main()
name_of_the_module.name_of_the_function
If you import it like
import test1 as t
then execution would be
t.main()
But now there is another issue. You cannot run test1.py independently. To overcome this
you need to add the following lines to the end of the test1 scriptif __name__ == "__main__": main()
or any other extra code which is needed to execute it independently.
if __name__ == "__main__": console.write('now i'm called directly\n') main()
Done.
As you see, test1.py needs to import Npp because every module/python script which get imported
will be imported to the local context and doesn’t have access to the global context automatically.Cheers
Claudia -
Hi Claudia
Thanks for your detailed response! Sounds great!
I happen to know a little about importing - I have made my own module with basic functions that I use often (e.g., getWord() to get current word etc.)
However, I didn’t know about thisif __name__ == "__main__":
What does this mean and do exactly?
How does it work - you write the function that you want to run? (I.e., in your case, the function name was “main” so you wrote “main”, but what if I have a different function name - do I declare that name, or should I just create one which guides the script?)Thanks,
Davey -
Hello Davey,
as said, the python interpreter reads your module/python script and executes all insecure code. Don’t know how to say this better.
Before it is done, the interpreter sets some special variables like __name__ and its value is __main__ only if this file is the main file.
( Btw there is an agreement in the python community that you shouldn’t mess with variables already defined which start with an
underscore. Variables defined by you can, of course, treated as you like)E.g. python.exe myfile.py
means, that __main__ refers to myfile.py and all code within will be executed, as long as everything is correct of course.
If myfile.py has an import mymodule then it’s __name__ variable is set to mymodule instead.
So if the mymodule gets loaded the interpreter doesn’t find __name__ == __main__ and does not execute code
which is under this if statement. Other code gets executed.
Instead you need to explicitly call it via mymodule.myfunction.So this line is simply a way to secure code against running.
Is this more understandable? I guess if you do the steps I described you will get it.
Cheers
Claudia -
Thanks Claudia!
Your suggestion works perfectly!This is what i experienced:
- When I ran the code with
if __name__ == "__main__":main()
everything worked perfectly - When I removed the if statement, and just wrote
main()
, the script got ran 2 times - I’m understanding, once while importing with theimport
statement, and then again when the script called it - When I run that script directly, it works in both instances (with and without the if condition)
As to why this is true, here is what I understood from testing:
- When the script is called directly, the
__main__
variable is always"__main__"
, which means… (not sure) - When the script is imported into a different script, the
__main__
variable is set to the name of the script being imported! - When the script is called from another script, then it is similar to running it directly, and the
__main__
variable is set to"__main__"
And after I wrote all that… I now can say that I understand your previous posts!
Thank you very much Claudia!
Davey - When I ran the code with
-
Hello Davey,
no, __name__ is the variable, __main__ the value.
consider the following in a script which gets imported by another scriptfrom Npp import * console.write('imported or called directly\n') if __name__ == "__main__": console.write('only if called directly\n')
if your scripts imports it you will only see the line 'imported or called directly
if you run the script directly you will see both.Why the need of this if…
You want to write a module which provides some basic function to other scripts.
Like, you have a convert module which converts what ever you want. Instead of writing the
function in evey script again and again you write a module and import it. I know you know this.
But what if you want to set up test routines which should check if the module is still working
after you have modified it? You don’t use another script to test it you write your test case under the if clause.
So they get not executed when some other script is importing it but when you call it directly.Cheers
Claudia -
Hey Claudia!
Nice! I understand now fully!
(I got mixed up with the name of the variable and the value…)You’re wonderful!!
Thank you
Davey