Is there a way for a program to invoke another program in python?
Let me explain my problem:
I am building an application (program 1) , I am also writing a debugger to catch exceptions (program 2) in program 1 { a typical try : except: } block of code . Now I want to release program 2 so that for any application like prog 1 , prog 2 can handle exceptions ( making my work easier) . I just want prog 1 to use a simple piece of code like:
import prog2
My confusion stems from the fact as how can I do something like this , how can I invoke prog 2 in prog 1, ie it should function as all the code in prog 1 should run in the {try: (prog 1) , except:} prog 2 try block.
Any pointers on how I can do this or a direction to start would we very much appreciated.
Note: I am using python 2.7 and IDLE as my developer tool.
tried execfile() yet? Read up on it on how to execute another script from your script.
I think you need to think about classes instead of scripts.
What about this?
class MyClass:
def __init__(self, t):
self.property = t
self.catchBugs()
def catchBugs(self):
message = self.property
try:
assert message == 'hello'
except AssertionError:
print "String doesn't match expected input"
a = MyClass('hell') # prints 'String doesn't match expected input'
UPDATE
I guess you have something like this in your directory:
program1.py (main program)
program2.py (debugger)
__init__.py
Program1
from program2 import BugCatcher
class MainClass:
def __init__(self, a):
self.property = a
obj = MainClass('hell')
bugs = BugCatcher(obj)
Program2
class BugCatcher(object):
def __init__(self, obj):
self.obj = obj
self.catchBugs()
def catchBugs(self):
obj = self.obj
try:
assert obj.property == 'hello'
except AssertionError:
print 'Error'
Here we are passing the whole object of your program1 to the BugCatcher object of program2. Then we access some property of that object to verify that it's what we expect.
Related
I am not able to explain the behaviour of the following code when running it in PyCharm:
class Empty:
def __init__(self):
pass
def __str__(self):
print('in!')
return f'<{__name__}.Empty object at {hex(id(self))!r}>'
if __name__ == '__main__':
e = Empty()
The output:
in!
in!
There is no output when running the code from the terminal like this python .\my_script.py. May someone have an explanation for this? Thanks!
ipdb is just great; wow. The thing is, when a script blows up, I still have to go into the code and add four lines that require not a ton of typing, but not nothing either. For example, let's say this is the bad line:
1 = 2
Naturally, I get this:
SyntaxError: can't assign to literal
If for whatever reason I wanted to debug that line and see what was going on just before that line (or somewhere else in the stack at that moment), I would typically change that line of code as follows:
try:
1 = 2
except:
import traceback;traceback.print_exc()
import ipdb;ipdb.set_trace()
That gets the job done, but I'd love to be able to run a script in a "mode" where whenever ANYTHING blows up (assuming the exception is otherwise unhandled), I get the same result.
Does that exist?
*******EDIT*******
Thanks to #np8's response, I redid the driver script to look like this (where main is any arbitrary function):
if __name__ == "__main__":
start = time.time()
args = parser.parse_args()
if args.verbosity > 1:
from ipdb import launch_ipdb_on_exception
with launch_ipdb_on_exception():
print("Launching ipdb on exception!")
main(start, args)
else:
print("NOT launching ipdb on exception!")
main(start, args)
This allows me, from the command line, to determine whether exceptions should launch ipdb (i.e. when I'm developing) or not (i.e. when the script is running in production and therefore with a verbosity argument below 2, in this example).
What you are looking for is "post mortem debugging". The easiest way to get what you want is to run the script using
ipdb script.py
or
python -m pdb script.py
instead of
python script.py
You could use the launch_ipdb_on_exception context manager:
# test.py
from ipdb import launch_ipdb_on_exception
with launch_ipdb_on_exception():
print(x)
Running the above will result into launching ipdb:
python .\test.py
NameError("name 'x' is not defined",)
> c:\tmp\delete_me\test.py(4)<module>()
2
3 with launch_ipdb_on_exception():
----> 4 print(x)
ipdb>
pm is a function decorator that mirrors the functionality of the
ipdb context manager launch_ipdb_on_exception. Use it to decorate
a function, and that function will go to ipdb on error.
The name 'pm' comes from the ipdb.pm() function, which stands for
postmortem, and behaves similarly.
With this, you can decorate the top-level function which you want to debug with #pm, and any exception at that level, or below, in the call stack will trigger ipdb.
import ipdb
class Decontext(object):
"""
Makes a context manager also act as decorator
"""
def __init__(self, context_manager):
self._cm = context_manager
def __enter__(self):
return self._cm.__enter__()
def __exit__(self, *args, **kwds):
return self._cm.__exit__(*args, **kwds)
def __call__(self, func):
def wrapper(*args, **kwds):
with self:
return func(*args, **kwds)
return wrapper
pm = Decontext(ipdb.launch_ipdb_on_exception())
In my python script I have a core dumped, and I think it's because the same function is called twice at the same time.
The function is the reading of a Vte terminal in a gtk window
def term(self, dPluzz, donnees=None):
text = str(self.v.get_text(lambda *a: True).rstrip())
[...]
print "Here is the time " + str(time.time())
def terminal(self):
self.v = vte.Terminal()
self.v.set_emulation('xterm')
self.v.connect ("child-exited", lambda term: self.verif(self, dPluzz))
self.v.connect("contents-changed", self.term)
Result:
Here is the time 1474816913.68
Here is the time 1474816913.68
Erreur de segmentation (core dumped)
How to avoid the double executing of the function?
The double execution must be the consequence of the contents-changed event triggering twice.
You could just check in your term function whether it has already been executed before, and exit if so.
Add these two lines at the start of the term function:
if hasattr(self, 'term_has_executed'): return
self.term_has_executed = True
I created a python decorator (mutli-platform compatible) which provide a mecanism to avoid concurrent execution.
The usage is :
#lock('file.lock')
def run():
# Function action
pass
Personnaly, I am used to using relative path :
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
#lock(os.path.join(CURRENT_FILE_DIR, os.path.basename(__file__)+".lock"))
The decorator :
import os
def lock(lock_file):
"""
Usage:
#lock('file.lock')
def run():
# Function action
"""
def decorator(target):
def wrapper(*args, **kwargs):
if os.path.exists(lock_file):
raise Exception('Unable to get exclusive lock.')
else:
with open(lock_file, "w") as f:
f.write("LOCK")
# Execute the target
result = target(*args, **kwargs)
remove_attempts = 10
os.remove(lock_file)
while os.path.exists(lock_file) and remove_attempts >= 1:
os.remove(lock_file)
remove_attempts-=1
return result
return wrapper
return decorator
For mutlithread calls
There is a unix solution for manage multithread calls : https://gist.github.com/mvliet/5715690
Don't forget to thank the author of this gist (it's not me).
I'm beginner in Python and I have problem to run my function in command line, through IDLE it's working, but I need to run it in command line, because I will have to make from it executable file...
So my problem... I have this
file name test.py
class A
def myFunction(a,b)
print a,b
myFunction calls Class, from IDLE it's enough to write myfunction(a,b), but from command line I don't know what to do
My goal is
to run function from command line with command: name_of_the_file arg1 arg2 --> test a b
I looked I think everywhere and tried everything, most common what I found was to add to my function this command
if __name__ == '__main__':
a = sys.argv[0]
b = sys.argv[1]
myFunction(a,b)
So it was
class A:
some process which calls myFunction
def myFunction(a,b)
print a,b
if __name__ == '__main__':
a = sys.argv[0]
b = sys.argv[1]
myFunction(a,b)
and then I called it from command line with test a b, but I got only errors
I use Python 2.7
Thank you for your help
Some issues with your code:
Python is case-sensitive. The keyword is class, not Class.
After the line class A there has to be a colon: class A:
If the function myFunction is supposed to be part of class A, it has to be indented:
class A:
def myFunction(a,b)
Methods of classes should have self as first parameter: def myFunction(self, a, b)
After def myFunction(self, a,b) there has to be a colon: def myFunction(self, a,b):
Your function must have at least one line of indented code following. If it is supposed to do nothing, you can use the keyword `pass:
def myFunction(self, a,b):
pass
If you want to use sys.argv you first have to import sys at the beginning of your code with import sys.
myFunction is part of a class, you first have to instantiate it to use the function:
Av = A()
Av.myFunction(a,b)
The first commandline argument is the second entry of sys.argv, not the first.
However it seems to me that you don't want a class anyway, so just write:
def myFunction(a,b):
pass
if __name__ == '__main__':
a = sys.argv[1]
b = sys.argv[2]
myFunction(a,b)
Also you call python scripts with python file.py arg1 arg2. If you want to omit python at the beginning then you can (in unix-like systems) add a shebang in the first line of the python-file: #!/usr/bin/env python. Then as long as the execution flag is set chmod +x file.py it may be called like ./file.py arg1 arg2.
Functions and Methods are 2 different things. Read more about it here. Methods must be called with their parent class as the first argument:
class Fruit:
def Taste(self):
print "Yuck!"
# Call it
Fruit().Taste()
You could pass argv in this manner:
MyClass(*args, **kwargs).MyMethod(argv, **kwargs)
EDIT
Am I right in assuming that you'd like to pass 2 (or more) arguments to the command line so that they could be passed on to a function and executed? If yes, I'll try something simple here:
from sys import argv
try:
a = argv[1]
b = argv[2]
except IndexError:
print "Enter both arguments"
class Integer:
def Check(self, z):
if int(z) < 0:
print z, "is a negative integer"
elif int(z) > 0:
print z, "is a positive integer"
else:
print z, "is not an integer"
# Make instance
myclass = Integer()
# Call methods
myclass.Check(a)
myclass.Check(b)
I have a class blahtestCommand(sublime_plugin.ApplicationCommand) with a run, it fails.
Another class, I have with sublime_plugin.TextCommmand) works.
I am a little bit baffled with what the run definition should look like. I know java(did some OOP programming 10 years ago which I remember well), but I know very little python. (so I don't quite get about a class taking a parameter, as it wasn't in java but i'd make a weak guess it's a bit like 'extends'-inheritance- or 'implements').
I'm also trying to determine what in the ST2 API documentation would tell somebody that when a class has parameter of sublime_plugin.TextCommand, that the def run line should look like this def run(self, edit) whereas when a class has parameter sublime_plugin.ApplicationCommand the def run should look like - I don't know what. (so that's an even bigger mystery)
Notice here the view.run_('......') doesn't work for class blahtest, it's not printing 'aaaaaaaa'
I get no errors at all in the console. The plugin - whatever.py is loading fine. Hence one class run method runs, though the other's doesn't. blahtestCommand does load. I can put a line between def run and class blahtestCommand to print "123456789" and it prints as soon as I save whatever.py 'cos it reloads and no errors. It's just its run method isn't getting called when I do view.run_command('blahtest')
import sublime, sublime_plugin
class blahtestCommand(sublime_plugin.ApplicationCommand):
def run(self):
print "aaaaaaaaaaa"
class butthiswillworkCommand(sublime_plugin.TextCommand):
def run(self, edit):
print "bbbb"
>>> view.run_command('blahtest')
>>> view.run_command('butthiswillwork')
bbbb
added
by complete weird luck I managed to get it working for WindowCommand
window.run_command('saef4',{"string":"abcd"})
, {"keys": ["ctrl+s", "ctrl+d"], "command": "saef4", "args": {"string": "abcd"} }
class saef4Command(sublime_plugin.WindowCommand):
def run(self,string):
print "uabcccc"
I might update this question further in future regarding running 'run' in the sublime api classes.
For #1, you are right. In Python, this means inheritance. The syntax for a derived class definition looks like class DerivedClass(BaseClassName):.
Inheritance in Python
For #2, Sublime Text 2 supports three types of commands. The run method is invoked when you run a command. Besides the required parameter, you can define as many parameters as you want for run. When you run a command with extra parameters, you need to pass these parameters in a map.
ApplicationCommand: command for the whole Sublime Text 2. No required parameter.
WindowCommand: command for a window. No required parameter.
TextCommand: command for a view. One required parameter, edit.
For #3, how to run:
ApplicationCommand: sublime.run_command('application_command_name'). Check run_command function for sublime module in the API reference.
WindowCommand: window.run_command('window_command_name'). Check run_command method of sublime.Window.
TextCommand: view.run_command('text_command_name'). Check run_command method of sublime.View
Example 1: commands without extra parameters
import sublime, sublime_plugin
class TestApplicationCommand(sublime_plugin.ApplicationCommand):
def run(self):
print("running TestApplicationCommand")
import sublime, sublime_plugin
class TestWindowCommand(sublime_plugin.WindowCommand):
def run(self):
print("running TestWindowCommand")
import sublime, sublime_plugin
class TestTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
print("running TestTextCommand")
Run these commands:
>>> sublime.run_command('test_application')
running TestApplicationCommand
>>> window.run_command('test_window')
running TestWindowCommand
>>> view.run_command('test_text')
running TestTextCommand
Example 2: commands with extra parameters
import sublime, sublime_plugin
class TestApplicationCommand(sublime_plugin.ApplicationCommand):
def run(self, arg1, arg2):
print("running TestApplicationCommand")
print("arg1: " + arg1)
print("arg2: " + arg2)
import sublime, sublime_plugin
class TestWindowCommand(sublime_plugin.WindowCommand):
def run(self, arg1, arg2):
print("running TestWindowCommand")
print("arg1: " + arg1)
print("arg2: " + arg2)
import sublime, sublime_plugin
class TestTextCommand(sublime_plugin.TextCommand):
def run(self, edit, arg1, arg2):
print("running TestTextCommand")
print("arg1: " + arg1)
print("arg2: " + arg2)
Run these commands:
>>> sublime.run_command('test_application', {'arg1' : '1', 'arg2' : '2'})
running TestApplicationCommand
arg1: 1
arg2: 2
>>> window.run_command('test_window', {'arg1' : '1', 'arg2' : '2'})
running TestWindowCommand
arg1: 1
arg2: 2
>>> view.run_command('test_text', {'arg1' : '1', 'arg2' : '2'})
running TestTextCommand
arg1: 1
arg2: 2