在Python的子进程中列出索引超出范围

时间:2014-05-19 19:23:23

标签: python subprocess

我使用来自this的代码来为某些程序(本例中为BS.player)上下调高音量,但是在调用get_master_volume函数时我遇到了问题。我在pyHook的“OnKeyboardEvent”中使用它,这是代码的一部分:

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()

这是错误:

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

任何人都可以解释为什么会发生此错误以及导致错误的原因(我应该怎么做才能修复它)?

祝你好运!

编辑:

当我打印proc.communicate()时,我得到了这个错误,这意味着什么?

proc.communicate:'C:\Program' is not recognized as an internal or external comma
nd,
operable program or batch file.
('', None)

编辑2:

我修复了我的配置中指向错误的bsplayer.exe路径的错误后的新错误:

 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

2 个答案:

答案 0 :(得分:2)

uuuuh ...我只是看了你正在使用的另一个问题以及你完全没有的东西。您正尝试使用与前者无关的Windows程序amixer将发送到Linux程序bsplayer.exe的参数。 非常 不太可能正常工作!这就是为什么它不起作用的原因。比作另一个问题:

  

proc = subprocess.Popen(' / usr / bin / amixer sget Master',shell = True,stdout = subprocess.PIPE)

因此,问题的第一部分是在调用bsplayer.exe时解决您的问题,但您实际希望它做的事情不起作用。


你应该尝试以下方法来调用子进程:

proc = subprocess.Popen([config.get('main', input1), 'sget', 'Master'], stdout=subprocess.PIPE)

因为,虽然我没有太多关于Windows的经验。 python,我认为用shell调用它可能不会按预期工作,尝试将您的路径解释为参数。虽然如果你在论证中引用它可能会有效:

proc = subprocess.Popen('"%s" sget Master '%config.get('main', input1), shell=True,    stdout=subprocess.PIPE)
是什么导致我得出的结论是:

'C:\Program' is not recognized as an internal or external command,

通常意味着bsplayer.exe的路径在第一个空格处被切断。


编辑:

您可以运行以下内容,并将输出添加到您的问题中吗?

基本上:

  • 我在沟通之前移动了proc.wait()
  • 在第二步中移动了第四行输出的选择
  • 从输出列表
  • 中添加了一个打印件

我想知道的是,您所遇到的错误是由于communicate()无法正常工作,还是因为您在输出中得到的行少于四行。

因此,以下版本正在解决您的呼叫问题:

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])

虽然没有输出任何内容。

你的命令真的有用吗?!你真的尝试过这样做:

"C:\Program Files (x86)\Webteh\BSPlayer\bsplayer.exe" sget Master

在cmd中查看它是否有效?

答案 1 :(得分:1)

让我试着回答这些(实际上)你有的三个问题。

  1. 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
    

    这意味着[0]访问尝试访问空序列(不太可能),或者[4]尝试访问最多包含4个条目的序列,以便{{1} }不存在。

    显然,输出少于4行,因此[4]没有proc.communicate()[0].split('\n')条目。

    程序输出与预期不符,或其他错误。

  2. [4]

    proc.communicate

    nd,可操作程序或批处理文件。 ('',无)

    这似乎表明您的呼叫命令行有问题。

    proc.communicate:'C:\Program' is not recognized as an internal or external comma 似乎包含完整路径,位于config.get('main', input1)。因此,您应该使用C:\Program Files(在正确的级别)正确地围绕您的计划路径。

  3. 关闭文件的I / O

    通过检查呼叫追踪可以解决第三个问题。在这里我们可以看到调用事物的方式有问题:"调用失败,因为子进程的communicate()已经关闭。

    我不清楚为什么会这样;也许你打电话给stdout两次?在第一次通话时,它会关闭,当您尝试第二次通话时,由于communicate()已经被读出,它会失败。