I have a script a.py :
#!/usr/bin/env python
def foo(arg1, arg2):
return int(arg1) + int(arg2)
if __name__ == "__main__":
import sys
print foo(sys.argv[1], sys.argv[2])`
I now want to make a script that can run the first script and write the output of a.py to a file with some arguments as well. I want to make the automate_output(src,arglist) generate some kind of an output that I can write to the outfile :
import sys
def automate_output(src, arglist):
return ""
def print_to_file (src, outfile, arglist):
print "printing to file %s" %(outfile)
out = open(outfile, 'w')
s = open(src, 'r')
for line in s:
out.write(line)
s.close()
out.write(" \"\"\"\n Run time example: \n")
out.write(automate(src, arglist))
out.write(" \"\"\"\n")
out.close()
try:
src = sys.argv[1]
outfile = sys.argv[2]
arglist = sys.argv[3:]
automate(src, arglist)
print_to_file(src,outfile,arglist)
except:
print "error"
#print "usage : python automate_runtime.py scriptname outfile args"
I have tried searching around, but so far I do not understand how to pass arguments by using os.system with arguments. I have also tried doing :
import a
a.main()
There I get a NameError: name 'main' is not defined
Update :
I researched some more and found subprocess and I'm quite close to cracking it now it seems.
The following code does work, but I would like to pass args instead of manually passing '2' and '3'
src = 'bar.py'
args = ('2' , '3')
proc = subprocess.Popen(['python', src, '2' , '3'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print proc.communicate()[0]
This is not a function, it's an if statement:
if __name__ == "__main__":
...
If you want a main function, define one:
import sys
def main():
print foo(sys.argv[1], sys.argv[2])`
Then just call it if you need to:
if __name__ == "__main__":
main()
a.main() has nothing to do with if __name__=="__main__" block. The former calls a function named main() from a module, the latter executes its block if current module name is __main__ i.e., when a module is called as a script.
#!/usr/bin/env python
# a.py
def func():
print repr(__name__)
if __name__=="__main__":
print "as a script",
func()
Compare a module executed as a script and a function called from the imported module:
$ python a.py
as a script '__main__'
$ python -c "import a; print 'via import',; a.func()"
via import 'a'
See section Modules in the Python tutorial.
To get output from the subprocess you could use subprocess.check_output() function:
import sys
from subprocess import check_output as qx
args = ['2', '3']
output = qx([sys.executable, 'bar.py'] + args)
print output
Related
I'm trying to execute file1.py from file2 .py by using exec function.
exec(open('file1.py').read())
Now I want to pass parameter target='target.yaml' to file1.py from exec function. How I can do that ?
Please help
You can use subprocess module:
file1:
import subprocess
print("Running file1.py")
subprocess.run("python file2.py target.yaml", shell=True)
exit(0) # file2 will be opened in a new window
file2:
import sys
yaml_file = sys.argv[1]
print("Running file2.py : yaml target: " + yaml_file)
output:
Running file1.py
Running file2.py : yaml target: target.yaml
While the other answer is a very good solution, if you are writing both files yourself you should consider importing one into the other and calling the function from the other file directly.
file1.py:
import otherfile
argument = "Hello world!"
otherfile.fancy_function(argument)
otherfile.py:
def fancy_function(arg):
print(arg)
if __name__ == "__main__":
# If the file is called directly like `python otherfile.py` this will be executed
fancy_function("I have my own world too!")
I have this code:
from subprocess import Popen
link="abc"
theproc = Popen([sys.executable, "p1.py",link])
I want to send the variable "link" to p1.py,
and p1.py will print it.
something like this. here is p1.py:
print "in p1.py link is "+ link
How can I do that?
I'm assuming python refers to Python 2.x on your system.
Retrieve the command line argument in p1.py using sys.argv:
import sys
if not len(sys.argv) > 1:
print "Expecting link argument."
else:
print "in p1.py link is " + sys.argv[1]
There's a function subprocess.check_output that is easier to use if you only want to call a program and retrieve its output:
from subprocess import check_output
output = check_output(["python", "p1.py", "SOME_URL"])
print "p1.py returned the following output:\n'{}'".format(output)
Example output:
$ python call_p1.py
p1.py returned the following output:
'in p1.py link is SOME_URL
'
You have to parse the command line arguments in your p1.py to get it in a variable:
import sys
try:
link = sys.argv[1]
except IndexError:
print 'argument missing'
sys.exit(1)
I have a python script which call another python script from another directory. To do that I used subprocess.Popen :
import os
import subprocess
arg_list = [project, profile, reader, file, str(loop)]
where all args are string if not converted implicitely
f = open(project_path + '/log.txt','w')
proc = subprocess.Popen([sys.executable, python_script] + arg_list, stdin=subprocess.PIPE, stdout=f, stderr=f)
streamdata = proc.communicate()[0]
retCode = proc.returncode
f.close()
This part works well, because of the log file I can see errors that occurs on the called script. Here's the python script called:
import time
import csv
import os
class loading(object):
def __init__(self, project=None, profile=None, reader=None, file=None, loop=None):
self.project=project
self.profile=profile
self.reader=reader
self.file=file
self.loop=loop
def csv_generation(self):
f=open(self.file,'a')
try:
writer=csv.writer(f)
if self.loop==True:
writer.writerow((self.project,self.profile,self.reader))
else:
raise('File already completed')
finally:
file.close()
def main():
p = loading(project, profile, reader, file, loop)
p.csv_generation()
if __name__ == "__main__":
main()
When I launch my subprocess.Popen, I have an error from the called script which tell me that 'project' is not defined. It looks the Popen method doesn't pass arguments to that script. I think i'm doing something wrong, someone has an idea ?
When you pass parameters to a new process they are passed positionally, the names from the parent process do not survive, only the values. You need to add:
import sys
def main():
if len(sys.argv) == 6:
project, profile, reader, file, loop = sys.argv[1:]
else:
raise ValueError,("incorrect number of arguments")
p = loading(project, profile, reader, file, loop)
p.csv_generation()
We are testing the length of sys.argv before the assignment (the first element is the name of the program).
Hi I am writing python for the first time:
I have a existing getprop.py script that loads the property file and prints the value of a given property:
import sys
import util
if len(sys.argv) < 3:
print "Error! Usage is: getprop.py [propfile] [propname]"
sys.exit(1)
props = util.loadprops(sys.argv[1])
if sys.argv[2] in props:
print props(sys.argv[2]);
Now I need to get the value of a property in another py script, so I modified the above script such that I do not disturb its functionality and I can use it in another script:
import sys
import util
def getpropvalue(propfile, propname):
props = util.loadprops(propfile)
if propname in props:
return props[propname]
if len(sys.argv) < 3:
print "Error! Usage is: getprop.py [propfile] [propname]"
sys.exit(1)
else:
print getpropvalue(sys.argv[1], sys.argv[2]);
and then in other script I import getprop and call the method like getprop.getpropvalue(FILE_NAME, PROP_NAME)and it prints the value of the property on the screen.
why does it prints the value? Is there any better way to solve this problem?
There is a way to run the script only if it was called directly. Add those lines to the end of your getprop code:
if __name__ == "__main__":
main()
This way the main function is only going to be called if you run the script directly (not importing). Is that what you're looking for?
Some explanation: every running script has a __name__ variable that will be set to "__main__" if you run the script from an IDE or console like python script.py
Change your getprop.py to this:
import sys
import util
def getpropvalue(propfile, propname):
props = util.loadprops(propfile)
if propname in props:
return props[propname]
if __name__ == '__main__':
if len(sys.argv) < 3:
print "Error! Usage is: getprop.py [propfile] [propname]"
sys.exit(1)
else:
print getpropvalue(sys.argv[1], sys.argv[2]);
This will prevent the code from being executed when it is imported.
In one of my functions I'm calling an external program, using subprocess.check_call, which will produce output. How could I use doctest to make sure the output it's producing is the one I'm expecting?
Maybe this can help:
import sys
import tempfile
import subprocess
def example(output):
r""" Do something ...
>>> output = example('Processing file ...')
>>> print output # doctest:+ELLIPSIS
'Processing file ...'
Check how many file was processed.
>>> [line.startswith('Processing file')
... for line in output.splitlines()].count(True)
1
"""
cmd = "print '%s'" % (output, )
with tempfile.TemporaryFile() as output:
subprocess.check_call([sys.executable, '-c', cmd], stdout=output)
output.seek(0)
res = output.read()
return res
if __name__ == '__main__':
import doctest
doctest.testmod()
As you can see i used the argument stdout of the subprocess.check_call function so to be able to get the output of the command , beside that if you are not using the stdout argument (which i assume that is your case) i think it very hard to capture the command output.
Hope this was hopeful :)