Run a script in Spyder directly from another script in Spyder - python

I have a Main script in Spyder that calls several functions contained in 6 different scripts (.py). I had to this way because the scripts are also used in different projects.
Currently, I have to run each script (containing several functions each) separately by hand, which is tiring, by clicking in the "green triangle" before launching the Main Script so that the functions contained in each script are stored in the working environment.
My question is: Would it be possible to automatically run each script directly from the Main Script and not running one after the another by hand?

Try
from filename import *
instead of
import filename
No .py extension in the import.

When you execute an import statement, the source file being imported is executed. So, for example, if you have thing.py and you execute import thing, all the code in thing.py will be run.
Also, as noted in a comment by Sven Krüger: you can use runpy.run_path, which I think is overall a better solution than my original suggestion.

Related

Python import with modification

I always structure my repos in the following way.
repo/main.py
repo/scripts/script.py
…
In main.py, I import script.py in the following manner:
from scripts import script as sc
This always works unless I decide to make changes to script.py. After making changes, if I run main.py from shell, it still imports code from the older script.py without the current changes. Until now, what I would then is just create another branch. However, this leads to a lot of branches in the development process. Is there any way to avoid this? How else should I be importing from the scripts directory to avoid this?
Help would be highly appreciated.
UPDATE
From the answers, I can see that I have caused some confusion. What I mean when I say that I run main.py from shell, I mean executing it with python main.py from the terminal. One can think of main.py as a script that does some math and outputs the answer. In doing those math, it imports script.py from scripts that has additional functions that it (main.py) uses. After running main.py N times, if I choose to update script.py, and then I execute main.py again (in the terminal), it imports the old script.py again and does the math with the older code. The answer does not reflect the changes I just made to script.py. Until now, what I have done, when I have had to go through something like this is just create another new branch and literally copy-paste the old files and the newer script.py in the new branch and execute main.py in the shell. It does import the newer script.py then. One more thing I have noticed is that if I just create a new file as say script2.py and then import it in main.py as
from scripts import script2 as sc
it imports script2.py just as it should - it reflects all the changes made to script.py.
There’s no second import statement in main.py.
On the surface this question sounds like we're repeatedly running
$ python main.py,
which quickly executes and exits.
But from the symptom, it must be the case that
we have a long-lived REPL prompt repeatedly executing the main.py code.
The module you're looking for is
importlib.
Do this:
from importlib import reload
from scripts import script as sc
# [do stuff, then edit script.py]
reload(sc)
# [do more stuff, and see the effect of the edit]
What is going on here?
Well, if you repeatedly execute
import scripts.script
import scripts.script
it turns out that the 2nd and subsequent import does nothing.
It consults sys.modules, finds the module has already
been loaded, and reports "cache hit!" instead of doing
the hard work of pulling in that text file.
The purpose of the reload() function is to
do a cache invalidate and repeat the import, so it actually
pulls in python text from the (presumably edited) source file.
Suppose you have a short-lived $ python main.py process
that runs repeatedly, sometimes after a script.py edit.
So the in-memory sys.module cache is not relevant,
having been discarded each time the process exits.
There is another level of caching at work here.
Typically the cPython interpreter will read script.py,
parse, produce bytecode from the parse tree, and write
the bytecode to script.pyc. More than one output cache
directory is possible, depending on system details.
Upon being asked to read script.py, the interpreter
can look to see if the corresponding .pyc bytecode file
is available and fresh, and then declare "cache hit!",
in which case the .py source file is not even read.
Normally this works great, because source file updates
are infrequent (human editing speed), and the freshness
comparison of file timestamps is effective. If there's
something wrong with those timestamps the whole mechanism
won't work properly, and we might fail to notice the
source was recently edited. Perhaps you suffer from this.
First, identify the relevant .pyc bytecode file.
Then, run main, make an edit, delete the .pyc file,
re-run main, and notice that the edit took effect.
Let us know
how it goes.

Auto-compile other .py files imported as packages?

I have two .py files I wrote that I've imported into a third .py file to use:
(The top of driver.py)
import wafer_diagram
import LightIV
wafer_diagram.py and LightIV.py contain functions that I'm using in driver.py. However, whenever I have a cleared/restarted kernel, I have to run each individual .py file, otherwise they aren't defined in driver.py. Is there a way to automatically do this when I run driver.py? I am using Spyder with python 3.8. Thanks!
Edit: To clarify, after running wafer diagram.py and LightIV.py, I am able to use the functions in driver.py without issue. However, if I restart my kernel, and then try running driver.py, an error will throw that the two modules do not exist.
I was being very silly! Although I imported my other files, I was not calling on their functions correctly. For example, for the function print_struct() from LightIV.py, I would write in driver.py:
import LightIV
print_struct()
Instead, I should have written:
import LightIV
LightIV.print_struct()
The reason that I was able to get away with this for so long was likely due to how Spyder saves variables. I would run LightIV.py and wafer_diagram.py, "saving" their functions, and then using them later on instead of properly importing them.

How can I run the Python3 interpreter with variables/references/etc as defined in a python file?

I'm new to python and enjoying learning the language. I like using the interpreter in real time, but I still don't understand completely how it works. I would like to be able to define my environment with variables, imports, functions and all the rest then run the interpreter with those already prepared. When I run my files (using PyCharm, Python 3.6) they just execute and exit.
Is there some line to put in my .py files like a main function that will invoke the interpreter? Is there a way to run my .py files from the interpreter where I can continue to call functions and declare variables?
I understand this is a total newbie question, but please explain how to do this or why I'm completely not getting it.
I think you're asking three separate things, but we'll count it as one question since it's not obvious that they are different things:
1. Customize the interactive interpreter
I would like to be able to define my environment with variables, imports, functions and all the rest then run the interpreter with those already prepared.
To customize the environment of your interactive interpreter, define the environment variable PYTHONSTARTUP. How you do that depends on your OS. It should be set to the pathname of a file (use an absolute path), whose commands will be executed before you get your prompt. This answer (found by Tobias) shows you how. This is suitable if there is a fixed set of initializations you would always like to do.
2. Drop to the interactive prompt after running a script
When I run my files (using PyCharm, Python 3.6) they just execute and exit.
From the command line, you can execute a python script with python -i scriptname.py and you'll get an interactive prompt after the script is finished. Note that in this case, PYTHONSTARTUP is ignored: It is not a good idea for scripts to run in a customized environment without explicit action.
3. Call your scripts from the interpreter, or from another script.
Is there a way to run my .py files from the interpreter where I can continue to call functions and declare variables?
If you have a file myscript.py, you can type import myscript in the interactive Python prompt, or put the same in another script, and your script will be executed. Your environment will then have a new module, myscript. You could use the following variant to import your custom definitions on demand (assuming a file myconfig.py where Python can find it):
from myconfig import *
Again, this is not generally a good idea; your programs should explicitly declare all their dependencies by using specific imports at the top.
You can achieve the result you intend by doing this:
Write a Python file with all the imports you want.
Call your script as python -i myscript.py.
Calling with -i runs the script then drops you into the interpreter session with all of those imports, etc. already executed.
If you want to save yourself the effort of calling Python that way every time, add this to your .bashrc file:
alias python='python -i /Users/yourname/whatever/the/path/is/myscript.py'
You set the environment variable PYTHONSTARTUP as suggested in this answer:
https://stackoverflow.com/a/11124610/1781434

Python 3.5.1 in Anaconda 3 from JetBrains PyCharm IDE - environment objects

I am coming into Python from R, and installed Python 3.5 with Anaconda. Now, PyCharm console has a prompt identical to an iPython Notebook, i.e. instead of >>>, it shows [1] at the command line.
After writing a toy line of code (below) in a .py document, and running it from within PyCharm, showing no errors, I was under the assumption that the function toss(), which was defined in the .py document would be ready to use in the console. However this did not seem to be the case. I ended up copying and pasting the pertinent lines of code on the console, entering, and then, finally, the function toss() was accessible to produce random examples of the roll of a die.
Logically, there has to be a smoother way of moving code from a .py file in the Editor to the environment accessible from the Python Console. But this shorter way doesn't seem to be simply running the .py file.
Code:
import random
def toss():
return(random.randint(1,6))
So how do you make the code in a Python file in the Editor accessible in the local environment?
You need to import it first. Let's say that your function toss() is in a file called foo.py then that means that you can do
from foo import toss
toss()
in your Python Console to use your function. A Python source file is, by definition, a module and you'll need to import it in order to use any functions defined there.

How to develop a Python module/package without having to restart the interpreter after every change?

I am developing a Python package using a text editor and IPython. Each time I change any of the module code I have to restart the interpreter to test this. This is a pain since the classes I am developing rely on a context that needs to be re-established on each reload.
I am aware of the reload() function, but this appears to be frowned upon (also since it has been relegated from a built-in in Python 3.0) and moreover it rarely works since the modules almost always have multiple references.
My question is - what is the best/accepted way to develop a Python module/package so that I don't have to go through the pain of constantly re-establishing my interpreter context?
One idea I did think of was using the if __name__ == '__main__': trick to run a module directly so the code is not imported. However this leaves a bunch of contextual cruft (specific to my setup) at the bottom of my module files.
Ideas?
A different approach may be to formalise your test driven development, and instead of using the interpreter to test your module, save your tests and run them directly.
You probably know of the various ways to do this with python, I imagine the simplest way to start in this direction is to copy and paste what you do in the interpreter into the docstring as a doctest and add the following to the bottom of your module:
if __name__ == "__main__":
import doctest
doctest.testmod()
Your informal test will then be repeated every time the module is called directly. This has a number of other benefits. See the doctest docs for more info on writing doctests.
Ipython does allow reloads see the magic function %run iPython doc
or if modules under the one have changed the recursive dreloadd() function
If you have a complex context is it possible to create it in another module? or assign it to a global variable which will stay around as the interpreter is not restarted
How about using nose with nosey to run your tests automatically in a separate terminal every time you save your edits to disk? Set up all the state you need in your unit tests.
you could create a python script that sets up your context and run it with
python -i context-setup.py
-i When a script is passed as first argument or the -c option is
used, enter interactive mode after executing the script or the
command. It does not read the $PYTHONSTARTUP file. This can be
useful to inspect global variables or a stack trace when a
script raises an exception.

Categories

Resources