Reloading a changed python file in emacs python shell - python

In the emacs Python shell (I'm running 2.* Python) I am importing a .py file I'm working with and testing the code. If I change the code however I'm not sure how to import it again.
From my reading so far it seems that
reload(modulename)
should work, but it doesn't seem to.
Perhaps just shutting down the python shell and restarting it would be enough, is there a command for that or you just do it manually?
edit: It looks like python-send-defun and python-send-buffer would be ideal, but changes don't seem to be propagating.

While reload() does work, it doesn't change references to classes, functions, and other objects, so it's easy to see an old version. A most consistent solution is to replace reload() with either exec (which means not using import in the first place) or restarting the interpreter entirely.
If you do want to continue to use reload, be very careful about how you reference things from that module, and always use the full name. E.g. import module and use module.name instead of from module import name. And, even being careful, you will still run into problems with old objects, which is one reason reload() isn't in 3.x.

It seems to work for me:
Make a file (in your PYTHONPATH) called test.py
def foo():
print('bar')
Then in the emacs python shell (or better yet, the ipython shell), type
>>> import test
>>> test.foo()
bar
Now modify test.py:
def foo():
print('baz')
>>> reload(test)
<module 'test' from '/home/unutbu/pybin/test.py'>
>>> test.foo()
baz

After looking at this issue for quite an extensive amount of time, I came to the conclusion that the best solution to implement is, either based on an initialisation file of your python interpreter (ipython for exemple), or using the python build-in module "imp" and its function "reload". For instance at the beginning of your code:
import my_module
import imp
imp.reload(my_module)
#your code
This solution came to me from this page: https://emacs.stackexchange.com/questions/13476/how-to-force-a-python-shell-to-re-import-modules-when-running-a-buffer

Related

Add a module when running a python program from terminal

I wrote a module that, if it is imported, automatically changes the error output of my program. It is quite handy to have it in almost any python code I write.
Thus I don't want to add the line import my_errorhook to every code I write but want to have this line added automatically.
I found this answer, stating that it should be avoided to change the behavior of python directly. So I thought about changing the command line, something like
python --importModule my_errorhook main.py
and defining an alias in the bashrc to overwrite the python command to automatically add the parameter. Is there any way I could achieve such a behavior?
There is no such thing like --importModule in python command line. The only way you can incept the code without explicitly importing is by putting your functions in builtins module. However, this is a practice that is discouraged because it makes your code hard to maintain without proper design.
Let's assume that your python file main.py is the entry point of the whole program. Now you can create another file bootstrap.py, and put below codes into the new file.
import main
__builtins__.func = lambda x: x>=0
main.main()
Then the function func() can be called from all modules without being imported. For example in main.py
def main():
...
print(func(1))
...

How to run a particular python script present in any other directory after a "if" statement in a python script?

I need to know how to run a python script from a python script present in other directory like the following algorithm:
if option==true
run /path/to/the/directory/PYTHON SCRIPT
else
ch3ka points out that you can use exec to do this. There are other ways like subprocess or os.system as well.
But Python works well with itself by design - this is the entire concept behind creating and importing modules. I think for most cases you'd be better off just encapsulating the script in a class, and moving the code that was previously in the if __name__ == '__main__' section of the script into the __init__ section of the class:
class PYTHON_SCRIPT:
def __init__(self):
# put your logic here
Then you could just import the class:
import PYTHON_SCRIPT
# no need to say if a boolean is true, just say if boolean
if option:
PYTHON_SCRIPT()
This would additionally give you the benefit of being able to use properties within your script as you saw fit.
use execfile.
execfile(...)
execfile(filename[, globals[, locals]])
Read and execute a Python script from a file.
The globals and locals are dictionaries, defaulting to the current
globals and locals. If only globals is given, locals defaults to it.
In pyton3, execfile is gone. You can use exec(open('/path/to/file.py').read()) instead.
Already answered here
How do I execute a program from python? os.system fails due to spaces in path
use subprocess module
import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
other methods include making system calls using os library or execfile in the other post
if the script is well designed it probably just launch a main function (often called main), so the most proper way to do this is to import this main function in your code and call it, this is the pythonic way. You just need to add the directory of the script into your python path.
if it's possible, always try to avoid exec, subprocess, os.system, Popen etc ..
example :
import sys
sys.path.insert(0, 'path/to/the/directory')
import python_script
sys.path.pop(0)
if option:
python_script.main()

python module import syntax

I'm teaching myself Python (I have experience in other languages).
I found a way to import a "module". In PHP, this would just be named an include file. But I guess Python names it a module. I'm looking for a simple, best-practices approach. I can get fancy later. But right now, I'm trying to keep it simple while not developing bad habits. Here is what I did:
I created a blank file named __init__.py, which I stored in Documents (the folder on the Mac)
I created a file named myModuleFile.py, which I stored in Documents
In myModuleFile.py, I created a function:
def myFunction()
print("hello world")
I created another file: myMainFile.py, which I stored in Documents
In this file, I typed the following:
import myModuleFile.py
myModuleFile.myFunction()
This successfully printed out "hello world" to the console when I ran it on the terminal.
Is this a best-practices way to do this for my simple current workflow?
I'm not sure the dot notation means I'm onto something good or something bad. It throws an error if I try to use myFunction() instead of myModuleFile.myFunction(). I kind of think it would be good. If there were a second imported module, it would know to call myFunction() from myModuleFile rather than the other one. So the dot notation makes everybody know exactly which file you are trying to call the function from.
I think there is some advanced stuff using sys or some sort of exotic configuration stuff. But I'm hoping my simple little way of doing things is ok for now.
Thanks for any clarification on this.
For your import you don't need the ".py" extension
You can use:
import myModuleFile
myModuleFile.myFunction()
Or
from myModuleFile import myFunction
myFunction()
Last syntax is common if you import several functions or globals of your module.
Besides to use the "main" function, I'd put this on your module:
from myModuleFile import myFunction
if __name__ == '__main__':
myFunction()
Otherwise the main code could be executed in imports or other cases.
I'd use just one module for myModuleFile.py and myMainFile.py, using the previous pattern let you know if your module is called from command line or as import.
Lastly, I'd change the name of your files to avoid the CamelCase, that is, I'd replace myModuleFile.py by my_module.py. Python loves the lowercase ;-)
You only need to have init.py if you are creating a package (a package in a simple sense is a subdirectory which has one or more modules in it, but I think it may be more complex than you need right now).
If you have just one folder which has MyModule.py and MyMainFile.py - you don't need the init.py.
In MyMainFile.py you can write :
import myModuleFile
and then use
myModuleFile.MyFunction()
The reason for including the module name is that you may reuse the same function name in more than one module and you need a way of saying which module your program is using.
Module Aliases
If you want to you can do this :
import myModuleFile as MyM
and then use
MyM.MyFunction()
Here you have created MyM as an alias for myModuleFile, and created less typing.
Here Lies Dragons
You will sometimes see one other forms of IMport, which can be dangerous, especially for the beginner.
from myModuleFile import MyFunction
if you do this you can use :
MyFunction()
but this has a problem if you have used the same function name in MyMainFile, or in any other library you have used, as you now can't get to any other definition of the name MyFunction. This is often termed Contaminating the namespace - and should really be avoided unless you are absolutely certain it is safe.
there is a final form which I will show for completeness :
from myModuleFile import *
While you will now be able to access every function defined in myModuleFile without using myModuleFile in front of it, you have also now prevented your MyMainFile from using any function in any library which matches any name defined in myModuleFile.
Using this form is generally not considered to be a good idea.
I hope this helps.

Linking Python Files Assistance

I understand how to actually link python files, however, i don't understand how to get variable's from these linked files. I've tried to grab them and I keep getting NameError.
How do I go about doing this? The reason i want to link files is to simply neaten up my script and not make it 10000000000 lines long. Also, in the imported python script, do i have to import everything again? Another question, do i use the self function when using another scripts functions?
ie;
Main Script:
import sys, os
import importedpyfile
Imported Py File
import sys, os
I understand how to actually link python files, however, i don't
understand how to get variable's from these linked files. I've tried
to grab them and I keep getting NameError.
How are you doing that? Post more code. For instance, the following works:
file1.py
#!/usr/bin/env python
from file2 import file2_func, file2_variable
file2_func()
print file2_variable
file2.py:
#!/usr/bin/env python
file2_variable = "I'm a variable!"
def file2_func():
print "Hello World!"
Also, in the imported python script, do i have to import everything
again?
Nope, modules should be imported when the python interpreter reads that file.
Another question, do i use the self function when using another
scripts functions?
Nope, that's usually to access class members. See python self explained.
There is also more than one way to import files. See the other answer for some explanations.
I think what you are trying to ask is how to get access to global vars from on .py file without having to deal with namespaces.
In your main script, replace the call to import importedpyfile to say this instead
from importedpyfile import *
Ideally, you keep the code the way you have it. But instead, just reference those global vars with the importedpyfile namespace.
e.g.
import importedpyfile
importedpyfile.MyFunction() # calls "MyFunction" that is defined in importedpyfile.py
Python modules are not "linked" in the sense of C/C++ linking libraries into an executable. A Python import operation creates a name that refers to the imported module; without this name there is no (direct) way to access another module.

Is this __import__ functionality correct?

I have a package named jiva_tasks, which I'm trying to import via celery (using the CELERY_IMPORTS attribute of celeryconfig. The import statement that celery is using is this:
__import__(module, [], [], [''])
Oddly enough, when this syntax is used, the module gets imported twice, once as jiva_tasks and another time as jiva_tasks. (with a period at the end). Now, chances are good that celery should be passing in globals rather than an empty list, but this seems broken to me. It seems odd that even if given the wrong arguments, __import__ would import something that isn't a valid python module name.
I know that the way to fix this is to pass in globals, but I want to understand why I'm getting this result. Is this a bug, or is there something I don't understand about how __import__ is working?
Update: It also seems to be working fine if I use importlib.
Update 2: Here's the sys.meta_path and sys.import_path right before the __import__ line gets executed:
>>> sys.meta_path
[]
>>> sys.path_hooks
[<type 'zipimport.zipimporter'>]
It doesn't appear to me that there's anything out of the ordinary. However, I just now realized that the package I'm importing is installed using setuptools' develop command. Does that make a difference?
Creating an empty file "foo.py" and then creating a "bar.py" that says:
__import__('foo', [], [], [''])
import sys
print sorted(sys.modules)
prints out a list that only includes foo once, and not foo. or anything else with a trailing dot — so it's not simply the fact that celery is using __import__ that is causing the problem here. Can you figure out what additional step celery is taking that adds the second module? (Or does a print sorted(sys.modules) right before and after the __import__() call suggest that both modules appear at that moment — in which case we need to look at what import hooks are defined at the moment of the import?)

Categories