Exception str() failed - python

I'm starting to create a new 3D scanner with a Raspberry Pi 3B + and a Canon 6D. I have a part of the Python code to recover the images thanks to the gphoto2 library but I can't put my ISO configuration on the reflex.
I have already done several tests but nothing works. I always have the same error:
I use the gp command to send all parameters to the Canon reflex.
Import :
import time
from datetime import datetime
from sh import gphoto2 as gp
import signal, os, subprocess, shutil
Gp command example (all works) :
CaptureImageDownload = ["--capture-image-and-download"]
CaptureImage = ["--capture-image"]
But this line don't work :
ValueISO = ["--set-config iso=0"]
Here is the error displayed in the command terminal
File "CameraShot.py", line 124, in <module>
gp(ValueISO)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 1427, in __call__
return RunningCommand(cmd, call_args, stdin, stdout, stderr)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 774, in __init__
self.wait()
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 792, in wait
self.handle_command_exit_code(exit_code)
File "/usr/local/lib/python2.7/dist-packages/sh.py", line 815, in handle_command_exit_code
raise exc
sh.ErrorReturnCode_1: <exception str() failed>
I can not write this command line otherwise my camera does not understand the order.

From the sh documentation on passing in arguments:
When passing multiple arguments to a command, each argument must be a separate string[.]
Yours are not separate strings. Split out the different parts (on spaces not surrounded by quotes):
ValueISO = ["--set-config", "iso=0"]
Also see the project's detailed explanation on why this is; but the short answer is that sh is not parsing arguments into separate strings like a shell would.
You can also use the shlex.split() function to handle the splitting for you:
ValueISO = shlex.split("--set-config iso=0")
Note that sh also supports using keyword arguments, where set_config="iso=0" is translated to ["--set-config", "iso=0"] for you. You could use that as:
value_iso = dict(set_config="iso=0")
then
gp(**value_iso)
That you get sh.ErrorReturnCode_1: <exception str() failed> is probably a bug in sh. Python uses type(exception).__name__: str(exception) as the last line of a traceback, and the str() call fails on the sh.ErrorReturnCode exception (sh.ErrorReturnCode_1 is a subclass of sh.ErrorReturnCode). I can see from the sh source code for the exception class that the error message is decoded from bytes to Unicode text, and Python 2 can't actually handle Unicode objects returned from a __str__ method. I've filed a bug report with sh to have that fixed.

Related

Running .exe without a console - OSError: [WinError 6] The handle is invalid

EDIT: Please note, I have seen other topics concerning this issue and already tried most of the suggestions there
I use pyinstaller to run an .exe file and now I am tryng to run it without a console (using the -w command).
One of my key libraries, patool, uses subprocesses, which gives the following error:
Traceback (most recent call last):
File "apscheduler\executors\base.py", line 125, in run_job
File "script.py", line 478, in Archiver
File "patoolib\__init__.py", line 521, in _create_archive
File "patoolib\__init__.py", line 421, in run_archive_cmdlist
File "patoolib\util.py", line 227, in run_checked
File "patoolib\util.py", line 219, in run
File "subprocess.py", line 339, in call
File "subprocess.py", line 753, in __init__
File "subprocess.py", line 1090, in _get_handles
OSError: [WinError 6] The handle is invalid
Here is the part of the patool util.py code which has the subprocesses.call() that gives the error:
def run (cmd, verbosity=0, **kwargs):
"""Run command without error checking.
#return: command return code"""
# Note that shell_quote_nt() result is not suitable for copy-paste
# (especially on Unix systems), but it looks nicer than shell_quote().
if verbosity >= 0:
log_info("running %s" % " ".join(map(shell_quote_nt, cmd)))
if kwargs:
if verbosity >= 0:
log_info(" with %s" % ", ".join("%s=%s" % (k, shell_quote(str(v)))\
for k, v in kwargs.items()))
if kwargs.get("shell"):
# for shell calls the command must be a string
cmd = " ".join(cmd)
if verbosity < 1:
# hide command output on stdout
with open(os.devnull, 'wb') as devnull:
kwargs['stdout'] = devnull
res = subprocess.call(cmd, **kwargs) <------------- ERROR
else:
res = subprocess.call(cmd, **kwargs)
return res
This is a common error, so I tried reading about subprocesses module and also dug out every single possible suggestion online, including:
adding kwargs['stdin'] = devnull, as suggested here: Python running as Windows Service: OSError: [WinError 6] The handle is invalid
adding shell=True to the call() method
adding subprocess._cleanup() at the start of the run() function
Neither of these works, the handler is still invalid. The programme works fine with the console active.
I am using Python 3.7, Anaconda3, 64-bit Windows 10 OS.
Later in the util.py there is a subprocess.popen() that I suspect will cause my the same problem.
I was trying to run the .exe by having the console active and then hiding it, but then I encounter other problems (it does not start upon system start up). I guess the console being present is pretty important, but I would love to get rid off it for better user experience.
Fixed it by adding: stdin=subprocess.PIPE in this file for python 3.8:
C:\Program Files (x86)\Python38-32\Lib*os.py* line 983 to 991
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, **stdin=subprocess.PIPE**, stderr=subprocess.STDOUT,bufsize=buffering)

How do I pass string parameter that has encoding problem from terminal?

I'm trying to pass a string parameter that has Korean characters. This causes an error, because Korean characters are apparently not properly encoded/decoded before it is passed to open() built-in function.
I wrote a command then executed it with os.system() which is equivalent to running it on the command prompt.
command = 'hwp5txt "C:\\Users\\username\\VSCodeProjects\\myproject\\data_files\\some_folder\\hwp\\2020-01-17_-_한국어가포함된 파일명(2020년도 제1차).hwp" > testdoc.txt'
os.system(command)
This throws an error because Korean characters are not properly decoded.
Traceback (most recent call last): File
"C:\Users\username\AppData\Local\pypoetry\Cache\virtualenvs\asiae-bok-nlp-xpMr0EW7-py3.7\Scripts\hwp5txt-script.py",
line 11, in
load_entry_point('pyhwp==0.1b12', 'console_scripts', 'hwp5txt')() File
"c:\users\username\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\hwp5\hwp5txt.py",
line 102, in main
with closing(Hwp5File(hwp5path)) as hwp5file: File "c:\users\username\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\hwp5\filestructure.py",
line 537, in init
stg = Hwp5FileBase(stg) File "c:\users\username\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\hwp5\filestructure.py",
line 188, in init
stg = OleStorage(stg) File "c:\users\username\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\hwp5\storage\ole.py",
line 35, in init
self.impl = impl_class(*args, **kwargs) File "c:\users\uesrname\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\hwp5\plat\olefileio.py",
line 112, in init
if not isOleFile(olefile): File "c:\users\username\appdata\local\pypoetry\cache\virtualenvs\asiae-bok-nlp-xpmr0ew7-py3.7\lib\site-packages\olefile\olefile.py",
line 309, in isOleFile
with open(filename, 'rb') as fp: OSError: [Errno 22] Invalid argument:
'C:\Users\username\VSCodeProjects\asiae-BOK-nlp\data_files\BOK_minutes\hwp\2020-01-17_-_???????
???(2020?? ?1?).hwp'
As you can see, OS Error was raised because the command I sent to the prompt somehow didn't manage to pass the right Korean characters, which is now ????? instead of its proper name.
I tried it on the terminal manually but it also fails.
How do I pass string characters that is not properly passed to the module?
I'm using the latest version of VSCode with Git Bash terminal.
Also, I can check this information. If you need further information, please comment.
sys.stdout.encoding
>> 'UTF-8'
sys.stdin.encoding
>> 'cp1252'
sys.getfilesystemencoding
>> 'UTF-8'
Turned out, this wasn't Python's problem nor VSCode. It was just hwp5txt's issue where hwp5txt.exe won't digest Korean sys.argv. It works by trying:
$ hwp5txt-script.py 'C:\\...\\한국어가포함된파일.hwp'
However, one thing that bugs me is that this script would work on the terminal but not on Jupyter Lab or .py script.
i.e,
os.system(command) or subprocess.run(command, shell=True) won't run.
Instead, they will raise an error popup that says:
"This file does not have an app associated with it for performing this
action. Please install an app or, if one is already installed, create
an association in the Default Apps Settings page."

Error: IOStream has no fileno - SUMO

I am trying to run SUMO through traci interface. I copy pasted this example from this link. The code is as follows
import os, sys
import subprocess
if 'SUMO_HOME' in os.environ:
tools = os.path.join(os.environ['SUMO_HOME'], 'tools')
sys.path.append(tools)
else:
sys.exit("please declare environment variable 'SUMO_HOME'")
PORT = 8813
sumoBinary = "C:/Program Files (x86)/DLR/Sumo/bin/sumo-gui"
sumoProcess = subprocess.Popen([sumoBinary, "-c", "example.sumocfg", \
"--remote-port", str(PORT)], stdout=sys.stdout, stderr=sys.stderr)
import traci
import traci.constants as tc
traci.init(PORT)
traci.vehicle.subscribe(vehID, (tc.VAR_ROAD_ID, tc.VAR_LANEPOSITION))
print(traci.vehicle.getSubscriptionResults(vehID))
for step in range(3):
print("step", step)
traci.simulationStep()
print(traci.vehicle.getSubscriptionResults(vehID))
traci.close()
When I try to run the code, it throws me the following error
File "C:\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 685, in runfile
execfile(filename, namespace)
File "C:\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 85, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
File "C:/Users/Raja/Documents/vehicomPhd/SUMOTraffic/traci.py", line 22, in <module>
"--remote-port", str(PORT)], stdout=sys.stdout, stderr=sys.stderr)
File "C:\Anaconda3\lib\subprocess.py", line 823, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "C:\Anaconda3\lib\subprocess.py", line 1037, in _get_handles
c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
File "C:\Anaconda3\lib\site-packages\IPython\kernel\zmq\iostream.py", line 205, in fileno
raise UnsupportedOperation("IOStream has no fileno.")
UnsupportedOperation: IOStream has no fileno.
Anyone know what is wrong.
Looks like you're running in an ipython notebook. They have non-standard "standard" I/O streams that can't be used like a "true" file object (because they're really data queues, not pipes, so they don't have a file descriptor to use for low level I/O).
You can't use them with libraries (like subprocess) that perform low level I/O; the error is there to tell you this.. You'll need to use a real file-like object, possibly something as simple as sending output to a tempfile.TemporaryFile and then copying output from the file to stdout if that's what you need.
It's possible it would work by just not passing Popen stdout and stderr arguments at all; the default behavior for subprocess is to use the same stdout and stderr as the parent, so if there are valid file handles opened (even if the notebook replaced sys.stdout/sys.stderr for Python use), it might "just work" (where "just work" includes the possibility that data sent to the underlying file descriptors 0 and 1 is discarded, so you never see it).
Or just don't run in the ipython notebook.
The problem was that my command line used Python 2 whereas the spyder IDE used python 3. Since I wont be needing to pass any more arguments to the stdin, I removed the option and simply tried to open the sumo-gui with subprocess as follows. It works now.
PORT = 8813
sumoBinary = 'C:/Program Files (x86)/DLR/Sumo/bin/sumo-gui'
sumoProcess = subprocess.Popen([sumoBinary, "-c", "Kaiserslautern.sumocfg", \
"--remote-port", str(PORT)])

subprocess.call() fails on Mac and Linux

I'm running into a weird issue with subprocess.call() function. I am trying to execute Java's 'jar' command using subprocess.call(). Here's the code:
import os
import subprocess
def read_war():
war_file_path = "jackrabbit-webapp-2.6.5.war"
java_home = os.environ['JAVA_HOME']
jar_path = os.path.join(java_home, 'bin', 'jar')
jar_cmd = jar_path + ' tvf ' + war_file_path
print "command to be executed is : " + jar_cmd
subprocess.call(jar_cmd)
read_war()
I'm using Python v2.7.3 on both Windows and Linux (Oracle Enterprise Linux).
On Windows 7, I see the contents of the war file being displayed. On Linux, however, I see a 'no such file or directory' error.:
$ python example.py
command to be executed is : /usr/local/tools/jdk1.7.0_15/bin/jar tvf jackrabbit-webapp-2.6.5.war
Traceback (most recent call last):
File "example.py", line 24, in <module>
read_war()
File "example.py", line 23, in read_war
subprocess.call(jar_cmd)
File "/usr/local/tools/Python-2.7.3/Lib/subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/local/tools/Python-2.7.3/Lib/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/local/tools/Python-2.7.3/Lib/subprocess.py", line 1249, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
$
I've tried the command '/usr/local/tools/jdk1.7.0_15/bin/jar tvf jackrabbit-webapp-2.6.5.war' from command prompt and it works fine. So, nothing's wrong with the command.
I've tried various combinations of subprocess.call() - passing a string, passing a list etc. None of them worked. Any help at all would be appreciated.
Add shell=True to the call. On windows, the CreateProcess command does string parsing to separate the command and its various arguments. On linux, you only get string processing if you specifically tell subprocess to call the shell. Otherwise, it treats that entire string you handed in as the command and you don't get very far.
subprocess.call(jar_cmd, shell=True)
Use a list (sequence) argument instead of a string as the docs say:
args is required for all calls and should be a string, or a sequence
of program arguments. Providing a sequence of arguments is generally
preferred, as it allows the module to take care of any required
escaping and quoting of arguments (e.g. to permit spaces in file
names). If passing a single string, either shell must be True (see
below) or else the string must simply name the program to be executed
without specifying any arguments.
Example:
import os
import subprocess
def read_war():
war_file_path = "jackrabbit-webapp-2.6.5.war"
jar_path = os.path.join(os.environ['JAVA_HOME'], 'bin', 'jar')
jar_cmd = [jar_path, 'tvf', war_file_path]
print("command to be executed is: %s" % jar_cmd)
subprocess.check_call(jar_cmd)
read_war()
I've used check_call to raise an exception if the command returns non-zero exit status.

Python - unable to call system command

I have some python code, from which I want to call another program. This program will
Print some output to STDOUT
Write a file to disk
Using call I get the following behavior;
from subprocess import call
call(['./tango_x86_64_release', 'VTS1 ct="N" nt="N" ph="7.2" te="303" io="0.02" seq="MKHPYEEFPTGSKSPYNMSRGAHPGAV"'])
34, File not properly written, try writing it up again,
1
This happens regardless if if the arguments are split into a list or not;
call(['./tango_x86_64_release', 'VTS1', 'ct="N"', 'nt="N"', 'ph="7.2"', 'te="303"', 'io="0.02"', 'seq="MKHPYEEFPTGSKSPYNMSRGAHPGAV"'])
34, File not properly written, try writing it up again,
1
I can call this same command from the my terminal
./tango_x86_64_release VTS1 ct="N" nt="N" ph="7.2" te="303" io="0.02" seq="MKHPYEEFPTGSKSPYNMSRGAHPGAV"
Which works and gives an exit status of 0.
It seems like its the writing to disk which is causing issues, if I break the command then I get the appropriate warning message (i.e. remove an argument, it warns me that the argument is missing).
Using subprocess.Popen() gives an OSError;
import subprocess as sub
output = sub.Popen('./tango_x86_64_release VTS1 ct="N" nt="N" ph="7.2" te="303" io="0.02" seq="MKHPYEEFPTGSKSPYNMSRGAHPGAV"', stdout=sub.PIPE, stderr=sub.PIPE)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1249, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Any help greatly appreciated
Use shlex.split to split the command for you:
import shlex
call(shlex.split('./tango_x86_64_release VTS1 ct="N" nt="N" ph="7.2" te="303" io="0.02" seq="MKHPYEEFPTGSKSPYNMSRGAHPGAV"'))
Note that although you might be able to solve your problem by adding shell=True, you should avoid it if possible, since it can be a security risk (search for "shell injection").
Try to add shell=True to the Popen call.
Also see:
Why does subprocess.Popen() with shell=True work differently on Linux vs Windows?
Popen error: [Errno 2] No such file or directory
Documentation (and why Passing shell=True can be a security hazard)

Categories