Greetings, I have a statement which sends different parameters to the termination and invokes a JAR file , apparently it invokes it, but when returning a response, it generates this error:
File "/var/www/html/facturacion/ventas/views.py" in GrabarVenta
374. tree = ET.XML(string_xml)
File "/usr/lib64/python2.7/xml/etree/ElementTree.py" in XML
1300. parser.feed(text)
File "/usr/lib64/python2.7/xml/etree/ElementTree.py" in feed
1642. self._raiseerror(v)
File "/usr/lib64/python2.7/xml/etree/ElementTree.py" in _raiseerror
1506. raise err
Exception Type: ParseError at /ventas/grabar_venta
Exception Value: syntax error: line 1, column 0
This error is due to the fact that my invocation must return a string of an xml signed in JAVA, apparently it does not return it and it returns this to me when invoking it:
Usage: java [-options] class [args...](to execute a class)
or java [-options] -jar jarfile [args...]
The command with which I invoke java is:
PATH_FIRMA_ABSOLUTA = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static/SRI/mifirma.p12')
PATH_FIRMAR_JAVA = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static/SRI/firmaXadesBes.jar')
file_pk12 = PATH_FIRMA_ABSOLUTA
password = 'Rgberv1792'
JAR_PATH = PATH_FIRMAR_JAVA
JAVA_CMD = 'java'
ds_document = False
#xml_str = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
PATH_XML_ABSOLUTO = os.path.join(os.path.dirname(os.path.dirname(__file__)),path_xml_generado)
tree = etree.parse(str(PATH_XML_ABSOLUTO))
xml_str = etree.tostring(tree, encoding='utf8', method='xml')
command = [
JAVA_CMD,
'-jar',
JAR_PATH,
xml_str,
base64.b64encode(file_pk12),
base64.b64encode(password)
]
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True
)
res = p.communicate()
Update
Performing as follows:
from lxml import etree
import shlex, subprocess
import base64 # encriptar archivo
from xml.etree import ElementTree as ET
import io
PATH_FIRMA_ABSOLUTA = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static/SRI/betty_elena_romo_vega.p12')
PATH_FIRMAR_JAVA = os.path.join(os.path.dirname(os.path.dirname(__file__)),'static/SRI/firmaXadesBes.jar')
file_pk12 = PATH_FIRMA_ABSOLUTA
password = 'Rgberv1792'
JAR_PATH = PATH_FIRMAR_JAVA
JAVA_CMD = 'java'
ds_document = False
PATH_XML_ABSOLUTO = os.path.join(os.path.dirname(os.path.dirname(__file__)),path_xml_generado)
tree = etree.parse(str(PATH_XML_ABSOLUTO))
xml_str = etree.tostring(tree, encoding='utf8', method='xml')
command = [
JAVA_CMD,
'-jar',
JAR_PATH,
xml_str,
base64.b64encode(file_pk12),
base64.b64encode(password)
]
print command
p = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
#shell=True
)
res = p.communicate()
# guardar xml firmado
documento_firmado = res[0]
print "DOCUMENTO JAVA FIRMADO"
print documento_firmado
# guardar xml firmado
string_xml = documento_firmado
tree = ET.XML(string_xml)
It works crazy in deployment mode with apache and mod_wsgi, but when uploading to the Amazon server that is in deploy mode with apache and mod_wsgi it generates the error:
Traceback:
File "/usr/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _legacy_get_response
249. response = self._get_response(request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/html/facturacionelectronica/ventas/views.py" in GrabarVenta
362. stderr=subprocess.STDOUT,
File "/usr/lib64/python2.7/subprocess.py" in __init__
711. errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py" in _execute_child
1327. raise child_exception
Exception Type: OSError at /ventas/grabar_venta
Exception Value: [Errno 2] No such file or directory
Thanks any suggestion..!!
If you use
shell=True
and pass an iterable asargs
only the first item is considered as the command to execute , the rest are arguments to the console itself (not to the executable)From the official documentation itself :
We can translate it something like this:
In your case, what Python executes is actually:
So it really just runs the command
java
, which simply returns the usage help.In short, if you have to use
shell = True
have to pass the command as a string, you can usestr.join
to avoid having to modify your code much:Edition
Although I commented above ( the string must be in exactly the same format as you would use in the console ), I've overlooked @Sal's good point in his comment. It is expected that you will need to enclose the string that represents the argument in quotes
xml_str
. Do the same for the rest of the arguments (such as base64 strings) if necessary. You can usestr.format
for that purpose and eventually escape any single quote that may exist within the string:In short, make sure that the resulting string is valid as a command for the console, Python passes it to sh as is. If you use Python 3 you can make use of
shlex.quote
together withstr.join
: