【发布时间】:2013-12-27 01:18:34
【问题描述】:
我正在尝试在 Windows 7 上的 vlc 播放器上编写类似的包装器,以便它可以通过按键加载文件夹中的下一个和上一个文件。我在其中所做的是,我将文件路径作为参数创建 vlc 类的实例并使用 pyHook,扫描键,当检测到特定击键时调用实例上的 play_next 和 play_prev 方法。这些方法通过杀死最后一个进程并使用 get_new_file 方法找到的下一个文件生成新的 vlc 来工作。它在前几次有效,然后给出了特殊的错误。
None
None
Traceback (most recent call last):
File "C:\Python27\pyHook\HookManager.py", line 351, in KeyboardSwitch
return func(event)
File "filestuff.py", line 64, in kbwrap
kbeventhandler(event,instance)
File "filestuff.py", line 11, in kbeventhandler
instance.play_prev()
File "filestuff.py", line 34, in play_prev
f=self.get_new_file(-1)
File "filestuff.py", line 40, in get_new_file
dirname= os.path.dirname(self.fn)
File "C:\Python27\lib\ntpath.py", line 205, in dirname
return split(p)[0]
File "C:\Python27\lib\ntpath.py", line 178, in split
while head2 and head2[-1] in '/\\':
TypeError: an integer is required
代码如下:
import os
import sys
import pythoncom, pyHook
import win32api
import subprocess
import ctypes
def kbeventhandler(event,instance):
if event.Key=='Home':
instance.play_prev()
if event.Key=='End':
instance.play_next()
return True
class vlc(object):
def __init__(self,filepath,vlcp):
self.fn=filepath
self.vlcpath=vlcp
self.process = subprocess.Popen([self.vlcpath, self.fn])
def kill(self):
PROCESS_TERMINATE = 1
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.process.pid)
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)
print self.process.poll()
def play_next(self):
self.kill()
f=self.get_new_file(1)
self.process = subprocess.Popen([self.vlcpath, f])
self.fn=f
def play_prev(self):
self.kill()
f=self.get_new_file(-1)
self.process = subprocess.Popen([self.vlcpath, f])
self.fn=f
def get_new_file(self,switch):
dirname= os.path.dirname(self.fn)
supplist=['.mkv','.flv','.avi','.mpg','.wmv']
files = [os.path.join(dirname,f) for f in os.listdir(dirname) if (os.path.isfile(os.path.join(dirname,f)) and os.path.splitext(f)[-1]in supplist)]
files.sort()
try: currentindex=files.index(self.fn)
except: currentindex=0
i=0
if switch==1:
if currentindex<(len(files)-1):i=currentindex+1
else:
if currentindex>0:i=currentindex-1
return files[i]
def main():
vlcpath='vlc'
if os.name=='nt': vlcpath='C:/Program Files (x86)/VideoLAN/VLC/vlc.exe'
fn='H:\\Anime\\needless\\Needless_[E-D]\\[Exiled-Destiny]_Needless_Ep11v2_(04B16479).mkv'
if len(sys.argv)>1:
fn=sys.argv[1] #use argument if available or else use default file
instance=vlc(fn,vlcpath)
hm = pyHook.HookManager()
def kbwrap(event):
kbeventhandler(event,instance)
hm.KeyDown = kbwrap
hm.HookKeyboard()
pythoncom.PumpMessages()
if __name__ == '__main__':
main()
【问题讨论】:
-
def kill(self): self.process.terminate() -
尝试将
close_fds=True传递给Popen(不会有问题)。 -
如果你删除
pyHook的东西并循环调用play_next()、play_prev()会发生什么? -
kill()的代码是为了避免:“第一次终止后无法访问。”不要在一行中使用多个语句(由于 cmets 的格式限制,我使用了它)。我认为如果您删除pyHook代码,那么错误就会消失。尝试在play_prev/next中设置一个标志,仅此而已。并在另一个读取此标志的线程中启动/停止 vlc。这个想法是避免从事件处理程序中启动子流程。 -
def kbwrap(event): return kbeventhandler(event,flag)#
标签: python windows-7 path subprocess