Reputation: 898
I was using code from this answer to turn volume up and down for certain program (BS.player in this case), but I'm having problems when calling get_master_volume function. I'm using it inside pyHook's "OnKeyboardEvent", here's that part of code:
def get_master_volume():
config.read('%s/config.cfg'%os.path.abspath(os.path.dirname(__file__)))
proc = subprocess.Popen('%s sget Master '%config.get('main', input1), shell=True, stdout=subprocess.PIPE) #config.get gives FULL and correct path to bsplayer.exe
amixer_stdout = proc.communicate()[0].split('\n')[4]
proc.wait()
find_start = amixer_stdout.find('[') + 1
find_end = amixer_stdout.find('%]', find_start)
return float(amixer_stdout[find_start:find_end])
def set_master_volume(volume):
config.read('%s/config.cfg'%os.path.abspath(os.path.dirname(__file__)))
val = float(int(volume))
proc = subprocess.Popen('%s sset Master '%config.get('main', input1) + str(val) + '%', shell=True, stdout=subprocess.PIPE) #config.get gives FULL and correct path to bsplayer.exe
proc.wait()
def OnKeyboardEvent(event):
#nothing important
if config.has_option('main', input1):
set_master_volume(get_master_volume() - 1)
print "New volume:", get_master_volume()
This is error:
File "c:/Users/Amar/Documents/volume+/main.py", line 53, in get_master_volume
amixer_stdout = proc.communicate()[0].split('\n')[4]
IndexError: list index out of range
Can anyone explain me why this error fires and what's causing it (and what should I do to fix it)?
Best regards!
EDIT:
When I print proc.communicate() out I get this errors, what this means?
proc.communicate:'C:\Program' is not recognized as an internal or external comma
nd,
operable program or batch file.
('', None)
EDIT 2:
New error after I fixed bug in my config which was pointing on wrong bsplayer.exe path:
Traceback (most recent call last):
File "c:\Python27\lib\site-packages\pyHook\HookManager.py", line 351, in Keybo
ardSwitch
return func(event)
File "c:/Users/Amar/Documents/volume+/main.py", line 101, in OnKeyboardEvent
set_master_volume(get_master_volume() - 1)
File "c:/Users/Amar/Documents/volume+/main.py", line 54, in get_master_volume
amixer_stdout = proc.communicate()[0].split('\n')[4]
File "c:\Python27\lib\subprocess.py", line 798, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "c:\Python27\lib\subprocess.py", line 478, in _eintr_retry_call
return func(*args)
ValueError: I/O operation on closed file
Upvotes: 3
Views: 4724
Reputation: 91049
Let me try to answer these (actually) three questions you have.
IndexError
File "c:/Users/Amar/Documents/volume+/main.py", line 53, in get_master_volume amixer_stdout = proc.communicate()[0].split('\n')[4] IndexError: list index out of range
This means that either the [0]
access tries to access an empty sequence (unlikely), or that [4]
tries to access a sequence which has a maximum of 4 entries, so that [4]
does not exist.
Obviously, the output has less than 4 lines, so proc.communicate()[0].split('\n')
has no [4]
entry.
Either the program output doesn't match the expectations, or something else is wrong.
proc.communicate
proc.communicate:'C:\Program' is not recognized as an internal or external comma
nd, operable program or batch file. ('', None)
This seems to indicate that there is something wrong with your call's command line.
config.get('main', input1)
seems to contain the full path, which lies in C:\Program Files
. So you should surround your program path properly with "
(at the right level).
I/O on closed file
This third problem can be resolved by inspecting the call trace. Here we can see that there is something wrong with the way things are called: the communicate()
call fails, as the stdout
of the subprocess is already closed.
It is unclear to me why this is the case; maybe you are calling communicate()
twice? On the first call, it is closed, and as you attempt a second call, it fails as stdout
has already been read out.
Upvotes: 1
Reputation: 24812
uuuuh… I just looked at the other question you're using and there's something you're totally missing. You're trying to use parameters sent to the linux program amixer
with your windows program bsplayer.exe
that has nothing related with the former. It is very unlikely to work! And it is the reason why it does not work. cf the other question:
proc = subprocess.Popen('/usr/bin/amixer sget Master', shell=True, stdout=subprocess.PIPE)
So the first part of the question is solving your problem in calling bsplayer.exe
, but what you actually want it to do does not work.
you should try the following to call the subprocess:
proc = subprocess.Popen([config.get('main', input1), 'sget', 'Master'], stdout=subprocess.PIPE)
because, though I don't have much experience with windows' python, I think that calling it with the shell might not work as expected, try to interpret your path as arguments. Though maybe if you put quotes around the argument it may work:
proc = subprocess.Popen('"%s" sget Master '%config.get('main', input1), shell=True, stdout=subprocess.PIPE)
what led me to that conclusion is that:
'C:\Program' is not recognized as an internal or external command,
usually means that the path to bsplayer.exe
is being cut at the first space.
edit:
Could you run the following, and add the output to your question?
Basically:
proc.wait()
before the communicatewhat I want to know is whether the error you're having is because of communicate()
not working, or because you get less than four lines in the output.
So the following version is solving your calling problem:
def get_master_volume():
config.read('%s/config.cfg'%os.path.abspath(os.path.dirname(__file__)))
p = [config.get('main', input1), 'sget', 'Master']
print("PROG:", p)
proc = subprocess.Popen(p, stdout=subprocess.PIPE)
proc.wait()
amixer_stdout = proc.communicate()[0].split('\n')
print("OUTPUT", amixer_stdout)
amixer_stdout = amixer_stdout[4]
find_start = amixer_stdout.find('[') + 1
find_end = amixer_stdout.find('%]', find_start)
return float(amixer_stdout[find_start:find_end])
though it outputs nothing.
Does your command actually work?! Did you actually try to do:
"C:\Program Files (x86)\Webteh\BSPlayer\bsplayer.exe" sget Master
in cmd to see if it works?
Upvotes: 2