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.
Related
I am aware of the difference between import x and from x import yyy, in the latter case one can address x-located functions by bare name, instead of full specification, and this exactly I want to do, I do not want to write full name every time.
Also I know how to redefine default Python dir on Windows so that it starts knowing my developed modules, and this is fine. However how to combine those two things altogether?
I want IDLE to get started knowing all functions from all my modules so I do not need to import them manually.
from * import *
i.e. for all modules in IDLE home directory?
P.S. I saw this question, however it puts solution only for one import and do not scan the whole dir, also this solution with shortcut parameters does not seem beautiful to me.
Are there any more neat ways?
If you start idle with -r file it will first run the file, or with -s, it will first run the file listed in the IDLESTARTUP or PYTHONSTARTUP environmental variables. Then test by starting IDLE in command prompt with, for instance, py -m idlelib -r file. Once this works, you could create on IDLE shortcut on your desktop (drag and drop from Start menu), open Properties, and add either of the above to the end of the 'Target'.
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.
I am trying to find ways to make better use of my time while programming.
I have a python script that does some heavy work (it can take hours) to finish. Now, most of the work it does is network related, so i have plenty of cpu resources to spare.
If the script was a C binary executable, it would be fine to git checkout onto a different branch and do extra work, I could even modify the binary in disk as it has been copied to ram, so until it finishes running I won't affect program output.
But python scripts are translated, not compiled. What happens if I start tampering with the source file, can i corrupt the programs output, or is the text file and associated imports copied to RAM, allowing me to tamper with the source with no risk of changing the behaviour of the running program?
In general, if you have a single Python file which you run as a script, you're fine. When you run the file, it is compiled into bytecode which is then executed. You can change the original script at this point and nothing breaks.
However, we can deliberately break it by writing some horrible but legal code like this:
horrible.py:
from time import sleep
sleep(10)
import silly
silly.thing()
silly.py:
def thing():
print("Wow!")
You can run horrible.py and while it is running you can edit silly.py on disk to make it do something else. When silly.py is finally imported, the updated version will be loaded.
A workaround is to put all your imports at the top of the file, which you probably do anyway.
When a python program is run it is compiled (kinda, more like translated) into a .pyc file that is then run by the python interpreter. When you change a file it should NOT affect the code if it is already running.
Here is a related stackoverflow answer. What will happen if I modify a Python script while it's running?
Why not have another working directory where you make your modifications? Is there a lot of ancillary data or something that makes it hard to set up a working directory? I.e. if your working directory is A, git clone A B, and then work in B. When you're done, you can pull the changes back from B to A:
git remote add B ../B
git pull B master
I am using IDLE to write a few small sized Python programs. There are two class files - node.py (Node Class) and position.py (Position class). I have my main module code in main.py from which I instantiate Node and Position objects.
What I have noticed is that - when I make a change in node.py or position.py, check the modules and then run them using F5 the changes are not reflected back when I run main.py as long as all the files are open in IDLE. I noticed that I have to manually close all the three .py files and then close IDLE, start over again and run main.py to see the changes made in node.py and position.py.
What is the issue here? Are my environment variables not being set correctly? I have searched SO and online but have not found a satisfactory answer.
[Details: I am using IDLE version 2.7.3 in Ubuntu. All the three .py files and the corresponding .pyc byte code files are in the same directory. This directory is also seen in sys.path]
What was happening is that I needed to use "import node" but I was using "from node import *" from main.py. This was preventing the main.py from linking to the updated node module!
(Sorry for accepting my own answer, but may be someone would also face the same problem later and hence I am uploading the solution)
I used Ctrl+F6 as Matthew Plourde suggested. Using Python 3 and IDLE, I would have my test file and my core file open. I would then fix errors reported by my assertions in my test file in my core file but the test file would not see the changes. The only solution I had was closing and reopening which is a pain. Ctrl+F6 did work. I could not find the reload function in Python3.
I retract this statement. With python3, if you run IDLE a "-n" because of lack of admin rights or some other security reason you need to import imp and use imp.reload(function) for IDLE to pickup any changes to other python files you are editing and recalling. Otherwise python does not detect the changes and will not reload the files.
http://docs.python.org/3.0/library/imp.html#imp.reload
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.