How to send jar file output to a json file using python - python

I have jar file when executed will print out the output on the terminal, Im not sure how can i pass the jar file output as a json file.
The code below just print the jar file output on the terminal
subprocess.Popen(['java', '-jar', '/home/myfolder/collect.jar'])
I'm thinking of below but no idea to start with...
with open('collect.json', 'w') as fp:
xxxxxxxxxxx
Hope someone could advise further. Thank you.

This should do the trick. If you look at the subprocess documentation you can see that check_output runs a command with arguments and return its output as a byte string.
import multiprocessing as mp
import subprocess
command = "java -jar /home/myfolder/collect.jar"
def runCommand(q):
commandOutput = subprocess.check_output(command.split()).decode("utf-8")
q.put(commandOutput)
q = mp.Queue()
commandProcess = mp.Process(target=runCommand, args=(q, ))
commandProcess.start()
output = q.get()
print(output)
with open('collect.json', w) as fp:
fp.write(output)
Didn't run the code, but should work.

You can try something like this
with open('collect.json','w') as fp :
subprocess.Popen('java -jar .//home/myfolder/collect.jar',stdout=fp).wait()
for further information, see this question How to get the output from .jar execution in python codes?
I hope this helped.

Related

How can I use an executable jar file with a mainClass in python? [duplicate]

I have been looking for an answer for how to execute a java jar file through python and after looking at:
Execute .jar from Python
How can I get my python (version 2.5) script to run a jar file inside a folder instead of from command line?
How to run Python egg files directly without installing them?
I tried to do the following (both my jar and python file are in the same directory):
import os
if __name__ == "__main__":
os.system("java -jar Blender.jar")
and
import subprocess
subprocess.call(['(path)Blender.jar'])
Neither have worked. So, I was thinking that I should use Jython instead, but I think there must a be an easier way to execute jar files through python.
Do you have any idea what I may do wrong? Or, is there any other site that I study more about my problem?
I would use subprocess this way:
import subprocess
subprocess.call(['java', '-jar', 'Blender.jar'])
But, if you have a properly configured /proc/sys/fs/binfmt_misc/jar you should be able to run the jar directly, as you wrote.
So, which is exactly the error you are getting?
Please post somewhere all the output you are getting from the failed execution.
This always works for me:
from subprocess import *
def jarWrapper(*args):
process = Popen(['java', '-jar']+list(args), stdout=PIPE, stderr=PIPE)
ret = []
while process.poll() is None:
line = process.stdout.readline()
if line != '' and line.endswith('\n'):
ret.append(line[:-1])
stdout, stderr = process.communicate()
ret += stdout.split('\n')
if stderr != '':
ret += stderr.split('\n')
ret.remove('')
return ret
args = ['myJarFile.jar', 'arg1', 'arg2', 'argN'] # Any number of args to be passed to the jar file
result = jarWrapper(*args)
print result
I used the following way to execute tika jar to extract the content of a word document. It worked and I got the output also. The command I'm trying to run is "java -jar tika-app-1.24.1.jar -t 42250_EN_Upload.docx"
from subprocess import PIPE, Popen
process = Popen(['java', '-jar', 'tika-app-1.24.1.jar', '-t', '42250_EN_Upload.docx'], stdout=PIPE, stderr=PIPE)
result = process.communicate()
print(result[0].decode('utf-8'))
Here I got result as tuple, hence "result[0]". Also the string was in binary format (b-string). To convert it into normal string we need to decode with 'utf-8'.
With args: concrete example using Closure Compiler (https://developers.google.com/closure/) from python
import os
import re
src = test.js
os.execlp("java", 'blablabla', "-jar", './closure_compiler.jar', '--js', src, '--js_output_file', '{}'.format(re.sub('.js$', '.comp.js', src)))
(also see here When using os.execlp, why `python` needs `python` as argv[0])
How about using os.system() like:
os.system('java -jar blabla...')
os.system(command)
Execute the command (a string) in a subshell. This is implemented by calling the Standard C function system(), and has the same limitations. Changes to sys.stdin, etc. are not reflected in the environment of the executed command.

To redirect os.system() output to a .txt file

I'm new to Python. I have list of Unix commmands ("uname -a","uptime","df -h","ifconfig -a","chkconfig --list","netstat -rn","cat /proc/meminfo","ls -l /dev") and I want to run them and redirect the entire output to a .txt file. I searched a lot but didn't get a proper solution, or I understood things wrongly.
I'm able to get the output on stdout with this for loop but I can't redirect to a file.
def commandsoutput():
command = ("uname -a","uptime","df -h","ifconfig -a","chkconfig --list","netstat -rn","cat /proc/meminfo","ls -l /dev")
for i in command:
print (os.system(i))
commandsoutput()
os.system returns the exit code of the command, not its output. It is also deprecated.
Use subprocess instead:
import subprocess
def commandsoutput():
command = ("uname -a","uptime","df -h","ifconfig -a","chkconfig --list","netstat -rn","cat /proc/meminfo","ls -l /dev")
with open('log.txt', 'a') as outfile:
for i in command:
subprocess.call(i, stdout=outfile)
commandsoutput()
This answer uses os.popen, which allows you to write the output of the command in your file:
import os
def commandsoutput():
commands = ("uname -a","uptime","df -h","ifconfig -a","chkconfig --list","netstat -rn","cat /proc/meminfo","ls -l /dev")
with open('output.txt','a') as outfile:
for command in commands:
outfile.write(os.popen(command).read()+"\n")
commandsoutput()

Fabric - Is there any way to capture run stdout?

I'm trying to do the following:
output = run("ls -l backups")
for line in output.split("/n"):
do_stuff(line)
Any way of having the stdout of ls sent to output?
To be more specific I'm using a CLI app called s3cmd which does something similar to ls, but with remote Amazon S3 buckets.
So a replacement for ls won't help unfortunately.
Exactly what you are asking for should be happening. From the docs:
run will return the result of the remote program’s stdout as a single (likely multiline) string.
run(), and related commands like local() and sudo(), return an _AttributeString object that is just a wrapper around stdout with attribute access to additional information like failure/success booleans, stderr, the command run, etc. The result object also has a stdout attribute, which is just more explicit.
To troubleshoot, print type(output), output to be sure the response is what you expect. Examine output.failed and output.stderr. It could be the command isn't doing what you expect, there is no "backups" directory, etc.
Try as below using String IO
from fabric.api import *
from StringIO import StringIO
fh = StringIO()
run("ls -l backups", stdout=fh)
fh.seek(0)
for line in fh.readlines():
do_stuff(line)
In case you need to use run(), you can do it like this:
with settings(
hide('warnings', 'running', 'stdout', 'stderr'),
warn_only=True
):
command = 'ls -l backups'
output = run(command)
for line in output.splitlines():
do_stuff(line)
For local() there is a bit more simple solution:
command = 'ls -l backups'
output = local(command, capture=True)
for line in output.splitlines():
do_stuff(line)
I hope it helps.
Try split using "\r\n":
output = run("ls -l backups")
output_stdout = output.stdout.split("\r\n")
You can also use this if you are using the local() api, by setting the capture=True
#task
def login_ecr_docker():
ecr_login = local("aws ecr get-login --region us-west-2", capture=True)
docker_login = ecr_login.stdout
status = local(docker_login, capture=True)
print (status.stdout)
Just simply return it:
def output():
return run("ls -l backups")
a = execute(output, host=hostname)
print a
a will be dictionary of results.

Linux, Write output to the file and terminate it using Python

There are various topics available on this very topic, "How to write output to the text file".
But my issue is different because the output to the command in question is continous.
What I want to do is, write the Output of the command cgps -s to the file aaa.txt
here is the code,
import signal
import os
import subprocess
p = subprocess.Popen(["cgps", "-s", ">> aaa.txt"], stdout=subprocess.PIPE,shell=True, preexec_fn=os.setsid)
os.killpg(p.pid, signal.SIGTERM)
The code doesn't work at all and no file is created with the name aaa.txt
When I execute this command through terminal,
cgps -s > aaa.txt
Then I have to press CTRL+C to terminate the output from being written on the output file because the output is continuous.
Is there any way to just capture one output and write it to the file and terminate it using Python or using Command line ?
So you are trying to create a pipe. Try this:
import subprocess
p = subprocess.Popen(["cgps", "-s"], stdout=subprocess.PIPE)
with open("aaa.txt", "w") as f:
while True:
line = p.stdout.readline()
if not line:
break
if some_condition(): # <-- check whether you have enough output
p.terminate()
break
f.writeline(line)
p.wait()

How to redirect stderr in Python?

I would like to log all the output of a Python script. I tried:
import sys
log = []
class writer(object):
def write(self, data):
log.append(data)
sys.stdout = writer()
sys.stderr = writer()
Now, if I "print 'something' " it gets logged. But if I make for instance some syntax error, say "print 'something# ", it wont get logged - it will go into the console instead.
How do I capture also the errors from Python interpreter?
I saw a possible solution here:
http://www.velocityreviews.com/forums/showpost.php?p=1868822&postcount=3
but the second example logs into /dev/null - this is not what I want. I would like to log it into a list like my example above or StringIO or such...
Also, preferably I don't want to create a subprocess (and read its stdout and stderr in separate thread).
I have a piece of software I wrote for work that captures stderr to a file like so:
import sys
sys.stderr = open('C:\\err.txt', 'w')
so it's definitely possible.
I believe your problem is that you are creating two instances of writer.
Maybe something more like:
import sys
class writer(object):
log = []
def write(self, data):
self.log.append(data)
logger = writer()
sys.stdout = logger
sys.stderr = logger
You can't do anything in Python code that can capture errors during the compilation of that same code. How could it? If the compiler can't finish compiling the code, it won't run the code, so your redirection hasn't even taken effect yet.
That's where your (undesired) subprocess comes in. You can write Python code that redirects the stdout, then invokes the Python interpreter to compile some other piece of code.
I can't think of an easy way. The python process's standard error is living on a lower level than a python file object (C vs. python).
You could wrap the python script in a second python script and use subprocess.Popen. It's also possible you could pull some magic like this in a single script:
import os
import subprocess
import sys
cat = subprocess.Popen("/bin/cat", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
os.close(sys.stderr.fileno())
os.dup2(cat.stdin.fileno(), sys.stderr.fileno())
And then use select.poll() to check cat.stdout regularly to find output.
Yes, that seems to work.
The problem I foresee is that most of the time, something printed to stderr by python indicates it's about to exit. The more usual way to handle this would be via exceptions.
---------Edit
Somehow I missed the os.pipe() function.
import os, sys
r, w = os.pipe()
os.close(sys.stderr.fileno())
os.dup2(w, sys.stderr.fileno())
Then read from r
To route the output and errors from Windows, you can use the following code outside of your Python file:
python a.py 1> a.out 2>&1
Source: https://support.microsoft.com/en-us/help/110930/redirecting-error-messages-from-command-prompt-stderr-stdout
Since python 3.5 you can use contextlib.redirect_stderr
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
For such a request, usually it would be much easier to do it in the OS instead of in Python.
For example, if you're going to run "a.py" and record all the messages it will generate into file "a.out", it would just be
python a.py 2>&1 > a.out
The first part 2>&1 redirects stderr to stdout (0: stdin, 1:stdout, 2:stderr), and the second redirects that to a file called a.out.
And as far as I know, this command works in Windows, Linux or MacOS! For other file redirection techniques, just search the os plus "file redirection"
I found this approach to redirecting stderr particularly helpful. Essentially, it is necessary to understand if your output is stdout or stderr. The difference? Stdout is any output posted by a shell command (think an 'ls' list) while sterr is any error output.
It may be that you want to take a shell commands output and redirect it to a log file only if it is normal output. Using ls as an example here, with an all files flag:
# Imports
import sys
import subprocess
# Open file
log = open("output.txt", "w+")
# Declare command
cmd = 'ls -a'
# Run shell command piping to stdout
result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
# Assuming utf-8 encoding
txt = result.stdout.decode('utf-8')
# Write and close file
log.write(txt)
log.close()
If you wanted to make this an error log, you could do the same with stderr. It's exactly the same code as stdout with stderr in its place. This pipes an error messages that get sent to the console to the log. Doing so actually keeps it from flooding your terminal window as well!
Saw this was a post from a while ago, but figured this could save someone some time :)
import sys
import tkinter
# ********************************************
def mklistenconsswitch(*printf: callable) -> callable:
def wrapper(*fcs: callable) -> callable:
def newf(data):
[prf(data) for prf in fcs]
return newf
stdoutw, stderrw = sys.stdout.write, sys.stderr.write
funcs = [(wrapper(sys.stdout.write, *printf), wrapper(sys.stderr.write, *printf)), (stdoutw, stderrw)]
def switch():
sys.stdout.write, sys.stderr.write = dummy = funcs[0]
funcs[0] = funcs[1]
funcs[1] = dummy
return switch
# ********************************************
def datasupplier():
i = 5.5
while i > 0:
yield i
i -= .5
def testloop():
print(supplier.__next__())
svvitch()
root.after(500, testloop)
root = tkinter.Tk()
cons = tkinter.Text(root)
cons.pack(fill='both', expand=True)
supplier = datasupplier()
svvitch = mklistenconsswitch(lambda text: cons.insert('end', text))
testloop()
root.mainloop()
Python will not execute your code if there is an error. But you can import your script in another script an catch exceptions. Example:
Script.py
print 'something#
FinalScript.py
from importlib.machinery import SourceFileLoader
try:
SourceFileLoader("main", "<SCRIPT PATH>").load_module()
except Exception as e:
# Handle the exception here
To add to Ned's answer, it is difficult to capture the errors on the fly during the compilation.
You can write several print statements in your script and you can stdout to a file, it will stop writing to the file when the error occurs. To debug the code you could check the last logged output and check your script after that point.
Something like this:
# Add to the beginning of the script execution(eg: if __name__ == "__main__":).
from datetime import datetime
dt = datetime.now()
script_dir = os.path.dirname(os.path.abspath(__file__)) # gets the path of the script
stdout_file = script_dir+r'\logs\log'+('').join(str(dt.date()).split("-"))+r'.log'
sys.stdout = open(stdout_file, 'w')
This will create a log file and stream the print statements to the file.
Note: Watch out for escape characters in your filepath while concatenating with script_dir in the second line from the last in the code. You might want something similar to raw string. You can check this thread for this.

Categories