Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
The community reviewed whether to reopen this question 10 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have a script named test1.py which is not in a module. It just has code that should execute when the script itself is run. There are no functions, classes, methods, etc. I have another script which runs as a service. I want to call test1.py from the script running as a service.
For example:
File test1.py:
print "I am a test"
print "see! I do nothing productive."
File service.py:
# Lots of stuff here
test1.py # do whatever is in test1.py
I'm aware of one method which is opening the file, reading the contents, and basically evaluating it. I'm assuming there's a better way of doing this. Or at least I hope so.
The usual way to do this is something like the following.
test1.py
def some_func():
print 'in test 1, unproductive'
if __name__ == '__main__':
# test1.py executed as script
# do something
some_func()
service.py
import test1
def service_func():
print 'service func'
if __name__ == '__main__':
# service.py executed as script
# do something
service_func()
test1.some_func()
This is possible in Python 2 using
execfile("test2.py")
See the documentation for the handling of namespaces, if important in your case.
In Python 3, this is possible using (thanks to #fantastory)
exec(open("test2.py").read())
However, you should consider using a different approach; your idea (from what I can see) doesn't look very clean.
Another way:
File test1.py:
print "test1.py"
File service.py:
import subprocess
subprocess.call("test1.py", shell=True)
The advantage to this method is that you don't have to edit an existing Python script to put all its code into a subroutine.
Documentation: Python 2, Python 3
import os
os.system("python myOtherScript.py arg1 arg2 arg3")
Using os you can make calls directly to your terminal. If you want to be even more specific you can concatenate your input string with local variables, ie.
command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
If you want test1.py to remain executable with the same functionality as when it's called inside service.py, then do something like:
test1.py
def main():
print "I am a test"
print "see! I do nothing productive."
if __name__ == "__main__":
main()
service.py
import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
I prefer runpy:
#!/usr/bin/env python
# coding: utf-8
import runpy
runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')
You should not be doing this. Instead, do:
test1.py:
def print_test():
print "I am a test"
print "see! I do nothing productive."
service.py
#near the top
from test1 import print_test
#lots of stuff here
print_test()
Use import test1 for the 1st use - it will execute the script. For later invocations, treat the script as an imported module, and call the reload(test1) method.
When reload(module) is executed:
Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called
A simple check of sys.modules can be used to invoke the appropriate action. To keep referring to the script name as a string ('test1'), use the 'import()' builtin.
import sys
if sys.modules.has_key['test1']:
reload(sys.modules['test1'])
else:
__import__('test1')
As it's already mentioned, runpy is a nice way to run other scripts or modules from current script.
By the way, it's quite common for a tracer or debugger to do this, and under such circumstances methods like importing the file directly or running the file in a subprocess usually do not work.
It also needs attention to use exec to run the code. You have to provide proper run_globals to avoid import error or some other issues. Refer to runpy._run_code for details.
Why not just import test1? Every python script is a module. A better way would be to have a function e.g. main/run in test1.py, import test1 and run test1.main(). Or you can execute test1.py as a subprocess.
I found runpy standard library most convenient. Why? You have to consider case when error raised in test1.py script, and with runpy you are able to handle this in service.py code. Both traceback text (to write error in log file for future investigation) and error object (to handle error depends on its type): when with subprocess library I wasn't able to promote error object from test1.py to service.py, only traceback output.
Also, comparing to "import test1.py as a module" solution, runpy is better cause you have no need to wrap code of test1.py into def main(): function.
Piece of code as example, with traceback module to catch last error text:
import traceback
import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy
from datetime import datetime
try:
runpy.run_path("./E4P_PPP_2.py")
except Exception as e:
print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time()))
print(traceback.format_exc())
print(e)
This process is somewhat un-orthodox, but would work across all python versions,
Suppose you want to execute a script named 'recommend.py' inside an 'if' condition, then use,
if condition:
import recommend
The technique is different, but works!
Add this to your python script.
import os
os.system("exec /path/to/another/script")
This executes that command as if it were typed into the shell.
An example to do it using subprocess.
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
This is an example with subprocess library:
import subprocess
python_version = '3'
path_to_run = './'
py_name = '__main__.py'
# args = [f"python{python_version}", f"{path_to_run}{py_name}"] # works in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()
if not error_:
print(output)
else:
print(error_)
According to the given example, this is the best way:
# test1.py
def foo():
print("hellow")
# test2.py
from test1 import foo # might be different if in different folder.
foo()
But according to the title, using os.startfile("path") is the best way as its small and it works. This would execute the file specified. My python version is 3.x +.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
The community reviewed whether to reopen this question 10 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have a script named test1.py which is not in a module. It just has code that should execute when the script itself is run. There are no functions, classes, methods, etc. I have another script which runs as a service. I want to call test1.py from the script running as a service.
For example:
File test1.py:
print "I am a test"
print "see! I do nothing productive."
File service.py:
# Lots of stuff here
test1.py # do whatever is in test1.py
I'm aware of one method which is opening the file, reading the contents, and basically evaluating it. I'm assuming there's a better way of doing this. Or at least I hope so.
The usual way to do this is something like the following.
test1.py
def some_func():
print 'in test 1, unproductive'
if __name__ == '__main__':
# test1.py executed as script
# do something
some_func()
service.py
import test1
def service_func():
print 'service func'
if __name__ == '__main__':
# service.py executed as script
# do something
service_func()
test1.some_func()
This is possible in Python 2 using
execfile("test2.py")
See the documentation for the handling of namespaces, if important in your case.
In Python 3, this is possible using (thanks to #fantastory)
exec(open("test2.py").read())
However, you should consider using a different approach; your idea (from what I can see) doesn't look very clean.
Another way:
File test1.py:
print "test1.py"
File service.py:
import subprocess
subprocess.call("test1.py", shell=True)
The advantage to this method is that you don't have to edit an existing Python script to put all its code into a subroutine.
Documentation: Python 2, Python 3
import os
os.system("python myOtherScript.py arg1 arg2 arg3")
Using os you can make calls directly to your terminal. If you want to be even more specific you can concatenate your input string with local variables, ie.
command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
If you want test1.py to remain executable with the same functionality as when it's called inside service.py, then do something like:
test1.py
def main():
print "I am a test"
print "see! I do nothing productive."
if __name__ == "__main__":
main()
service.py
import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
I prefer runpy:
#!/usr/bin/env python
# coding: utf-8
import runpy
runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')
You should not be doing this. Instead, do:
test1.py:
def print_test():
print "I am a test"
print "see! I do nothing productive."
service.py
#near the top
from test1 import print_test
#lots of stuff here
print_test()
Use import test1 for the 1st use - it will execute the script. For later invocations, treat the script as an imported module, and call the reload(test1) method.
When reload(module) is executed:
Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called
A simple check of sys.modules can be used to invoke the appropriate action. To keep referring to the script name as a string ('test1'), use the 'import()' builtin.
import sys
if sys.modules.has_key['test1']:
reload(sys.modules['test1'])
else:
__import__('test1')
As it's already mentioned, runpy is a nice way to run other scripts or modules from current script.
By the way, it's quite common for a tracer or debugger to do this, and under such circumstances methods like importing the file directly or running the file in a subprocess usually do not work.
It also needs attention to use exec to run the code. You have to provide proper run_globals to avoid import error or some other issues. Refer to runpy._run_code for details.
Why not just import test1? Every python script is a module. A better way would be to have a function e.g. main/run in test1.py, import test1 and run test1.main(). Or you can execute test1.py as a subprocess.
I found runpy standard library most convenient. Why? You have to consider case when error raised in test1.py script, and with runpy you are able to handle this in service.py code. Both traceback text (to write error in log file for future investigation) and error object (to handle error depends on its type): when with subprocess library I wasn't able to promote error object from test1.py to service.py, only traceback output.
Also, comparing to "import test1.py as a module" solution, runpy is better cause you have no need to wrap code of test1.py into def main(): function.
Piece of code as example, with traceback module to catch last error text:
import traceback
import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy
from datetime import datetime
try:
runpy.run_path("./E4P_PPP_2.py")
except Exception as e:
print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time()))
print(traceback.format_exc())
print(e)
This process is somewhat un-orthodox, but would work across all python versions,
Suppose you want to execute a script named 'recommend.py' inside an 'if' condition, then use,
if condition:
import recommend
The technique is different, but works!
Add this to your python script.
import os
os.system("exec /path/to/another/script")
This executes that command as if it were typed into the shell.
An example to do it using subprocess.
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
This is an example with subprocess library:
import subprocess
python_version = '3'
path_to_run = './'
py_name = '__main__.py'
# args = [f"python{python_version}", f"{path_to_run}{py_name}"] # works in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()
if not error_:
print(output)
else:
print(error_)
According to the given example, this is the best way:
# test1.py
def foo():
print("hellow")
# test2.py
from test1 import foo # might be different if in different folder.
foo()
But according to the title, using os.startfile("path") is the best way as its small and it works. This would execute the file specified. My python version is 3.x +.
Is it possible to intercept interpreter's code before it executes?
Let's say I want to handle a case like:
>>> for f in glob.glob('*.*'): # I'd like to intercept this code before it executes
... something_to_do(f) # and play with it in some dangerous fashion :)
...
ERROR: Using glob not allowed. # e.g.
But there are tons of other examples (like altering the code, or sending it somewhere).
I can write my own interpreter, but that's not really the point.
Ok, solved it by creating new module which starts new interpreter instance and do whatever.
I just put the code below in the module and import it.
import code
class GlobeFilterConsole(code.InteractiveConsole):
def push(self, line):
self.buffer.append(line)
source = "\n".join(self.buffer)
if 'glob' in source: # do whatever you want with the source
print('glob usage not allowed')
more = False
else:
more = self.runsource(source, self.filename)
if not more:
self.resetbuffer()
return more
console = GlobeFilterConsole()
console.interact()
I'm working on a Django project but I think this is a pure Python unittest question.
Normally, when you run tests, exceptions will be caught by the test runner and handled accordingly.
For debugging purposes, I want to disable this behavior, i.e. so that:
python -i manage.py test
will break into the interactive Python shell on an exception, as normal.
How to do that?
EDIT: based on the answers so far, it seems like this is more of a Django-specific question than I realized!
You can use django-nose test runner, it works with unittest tests, and run your tests like python manage.py test -v2 --pdb. And nose will run pdb for you.
A new app django-pdb makes this nicer, supporting a mode for breaking on test failures or uncaught exceptions in regular code.
You could try something like this in a module within your package, then use CondCatches(your exceptions,) in your code:
# System Imports
import os
class NoSuchException(Exception):
""" Null Exception will not match any exception."""
pass
def CondCatches(conditional, *args):
"""
Depending on conditional either returns the arguments or NoSuchException.
Use this to check have a caught exception that is suppressed some of the
time. e.g.:
from DisableableExcept import CondCatches
import os
try:
# Something like:
print "Do something bad!"
print 23/0
except CondCatches(os.getenv('DEBUG'), Exception), e:
#handle the exception in non DEBUG
print 'Somthing has a problem!', e
"""
if conditional:
return (NoSuchException, )
else:
return args
if __name__ == '__main__':
# Do SOMETHING if file is called on it's own.
try:
print 'To Suppress Catching this exception set DEBUG=anything'
print 1 / 0
except CondCatches(os.getenv('DEBUG'), ValueError, ZeroDivisionError), e:
print "Caught Exception", e
i.e. can you do something like:
if we_are_in_ipython:
do_some_ipython_specific_stuff()
normal_python_stuff()
I guess what I'm trying to do is very loosely along the lines of #if DEBUG in C# (i.e. using ipython as a debugging tool and command line python to run the code without the debugging stuff in there).
Check for the __IPYTHON__ variable:
def is_ipython():
try:
__IPYTHON__
return True
except:
return False
As explained on the duplicate, you can use the try/except method, or
if '__IP' in globals():
# stuff for ipython
pass
Or check the __IPYTHON__ in builtin:
import __builtin__
if hasattr(__builtin__, '__IPYTHON__'):
# stuff for ipython
pass
Yes.
if 'get_ipython' in dir():
"""
when ipython is fired lot of variables like _oh, etc are used.
There are so many ways to find current python interpreter is ipython.
get_ipython is easiest is most appealing for readers to understand.
"""
do_some_thing_
else:
don_sonething_else