如何使用unicode版本的Windows API:mciSendString(),Python
我正在Windows10:playsound上测试Python包 它似乎对路径名的某些字符有问题,例如“c:\sauté”和宽字符。所以它找不到文件 命令的错误275: 打开“C:\sauté.wav”别名playsound_0.4091468603477375 找不到指定的文件。确保路径和文件名正确 我尝试使用unicode版本如何使用unicode版本的Windows API:mciSendString(),Python,python,winapi,Python,Winapi,我正在Windows10:playsound上测试Python包 它似乎对路径名的某些字符有问题,例如“c:\sauté”和宽字符。所以它找不到文件 命令的错误275: 打开“C:\sauté.wav”别名playsound_0.4091468603477375 找不到指定的文件。确保路径和文件名正确 我尝试使用unicode版本mciSendStringW()。原来mciSendStringW根本无法识别编码的命令。我不知道我现在还能做什么 def winCommand(*命令): buf=c
mciSendStringW()
。原来mciSendStringW根本无法识别编码的命令。我不知道我现在还能做什么
def winCommand(*命令):
buf=c_缓冲区(255)
command=''.join(command).encode(getfilesystemencoding())
errorCode=int(windell.winmm.mciSendStringA(命令,buf,254,0))
如果出现错误代码:
errorBuffer=c_缓冲区(255)
windell.winmm.mcigeterorstringa(错误代码,错误缓冲区,254)
exceptionMessage=('\n Error'+str(errorCode)+'用于命令:'
'\n'+命令.解码()+
'\n'+errorBuffer.value.decode())
引发播放声音异常(例外消息)
返回基本单位值
prj现场:(包括安装和快速启动指南)
src代码:
Microsoft mciSendString函数:
使用宽函数时,
mciSendStringW
,不应对字符串进行编码。因此,您的行应该简单地读取command=''.join(command)
。至少在使用Python 3.6的Windows10机器上是这样
要再次检查,可以运行下面的代码。第二个错误代码是296,这只是抱怨它是错误的文件类型,因为我们为测试创建了一个空文件
从ctypes导入c_缓冲区,Windell
从sys导入getfilesystemencoding
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
buf=c_缓冲区(255)
filesystemencoding=getfilesystemencoding()
filename=r'.\sauté.wav'
#如果文件不存在,请创建该文件
文件=打开(文件名为“w+”)
file.close()文件
#ASCII码
命令='打开'+文件名
字节\字符串\命令=命令.编码(文件系统编码)
errorCode=int(windell.winmm.mciSendStringA(byte_string_命令,buf,254,0))
#错误代码应为275:找不到该文件
errorBuffer=c_缓冲区(255)
windell.winmm.mcigeterorstringa(错误代码,错误缓冲区,254)
打印(“{}:{}.”格式(errorCode,errorBuffer.value.decode())
#统一码
errorCode=int(windell.winmm.mciSendStringW(命令,buf,254,0))
#错误代码应为296:无法播放指定的文件
errorBuffer=c_缓冲区(255)
windell.winmm.mcigeterorstringa(错误代码,错误缓冲区,254)
打印(“{}:{}.”格式(errorCode,errorBuffer.value.decode())
使用wide函数时,mciSendStringW
不应对字符串进行编码。因此,您的行应该简单地读取command=''.join(command)
。至少在使用Python 3.6的Windows10机器上是这样
要再次检查,可以运行下面的代码。第二个错误代码是296,这只是抱怨它是错误的文件类型,因为我们为测试创建了一个空文件
从ctypes导入c_缓冲区,Windell
从sys导入getfilesystemencoding
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
buf=c_缓冲区(255)
filesystemencoding=getfilesystemencoding()
filename=r'.\sauté.wav'
#如果文件不存在,请创建该文件
文件=打开(文件名为“w+”)
file.close()文件
#ASCII码
命令='打开'+文件名
字节\字符串\命令=命令.编码(文件系统编码)
errorCode=int(windell.winmm.mciSendStringA(byte_string_命令,buf,254,0))
#错误代码应为275:找不到该文件
errorBuffer=c_缓冲区(255)
windell.winmm.mcigeterorstringa(错误代码,错误缓冲区,254)
打印(“{}:{}.”格式(errorCode,errorBuffer.value.decode())
#统一码
errorCode=int(windell.winmm.mciSendStringW(命令,buf,254,0))
#错误代码应为296:无法播放指定的文件
errorBuffer=c_缓冲区(255)
windell.winmm.mcigeterorstringa(错误代码,错误缓冲区,254)
打印(“{}:{}.”格式(errorCode,errorBuffer.value.decode())
虽然返回“0”(成功),但没有声音。我的是Python3.7和Win10。我还尝试了utf-8、utf-16-le,但没有效果。
您需要添加wait
标志。打开此标志后,您确实可以
等待调用的函数完成。你可以
播放你的文件。如果您将其移除,它将启动播放
然后马上关闭它
整个代码(ASCII):
UNICODE:
from ctypes import c_buffer, windll
from sys import getfilesystemencoding
if __name__ == '__main__':
buf = c_buffer(255)
filesystemencoding = getfilesystemencoding()
filename = r'.\file_example.mp3'
# ASCII
command = r'open ' + filename + r' alias test2'
waitcommand = r'play test2 wait'
byte_string_command = command.encode(filesystemencoding)
waiting = waitcommand.encode(filesystemencoding)
# Unicode
errorCode = int(windll.winmm.mciSendStringW(command, buf, 254, 0))
# errorCode should be 296: The specified file cannot be played
errorBuffer = c_buffer(255)
windll.winmm.mciGetErrorStringA(errorCode, errorBuffer, 254)
print("{}: {}".format(errorCode, errorBuffer.value.decode()))
errorCode = int(windll.winmm.mciSendStringW(waitcommand, buf, 254, 0))
# errorCode should be 275: Cannot find the file
errorBuffer = c_buffer(255)
windll.winmm.mciGetErrorStringA(errorCode, errorBuffer, 254)
print("{}: {}".format(errorCode, errorBuffer.value.decode()))
如果代码正常工作,它将返回0:执行了指定的命令
注意:
返回用于在Unicode之间转换的编码的名称
文件名和字节文件名。为了获得最佳兼容性,str应该是
用于所有情况下的文件名,但将文件名表示为
还支持字节。接受或返回文件名的函数
应支持str或bytes,并在内部转换为
系统的首选表示形式
This encoding is always ASCII-compatible.
[os.fsencode()][2] and [os.fsdecode()][3] should be used to ensure that the
correct encoding and errors mode are used.
In the UTF-8 mode, the encoding is utf-8 on any platform.
On macOS, the encoding is 'utf-8'.
On Unix, the encoding is the locale encoding.
On Windows, the encoding may be 'utf-8' or 'mbcs', depending on user
configuration.
Changed in version 3.6: Windows is no longer guaranteed to return
'mbcs'. See PEP 529 and [_enablelegacywindowsfsencoding()][4] for more
information.
Changed in version 3.7: Return ‘utf-8’ in the UTF-8 mode.
打开设备时,可以使用“别名”标志指定
设备的设备标识符。此标志允许您指定一个短字符
具有长文件名的复合设备的设备标识符,以及
它允许您打开同一文件或设备的多个实例
如果您希望播放无等待,则需要处理MCI\U NOTIFY
,设置
回调窗口句柄,并在
游戏结束了
:如果“notify”标志
已在命令字符串中指定
虽然返回“0”(成功),但没有声音。我的是Python3.7和Win10。我也不知道
This encoding is always ASCII-compatible.
[os.fsencode()][2] and [os.fsdecode()][3] should be used to ensure that the
correct encoding and errors mode are used.
In the UTF-8 mode, the encoding is utf-8 on any platform.
On macOS, the encoding is 'utf-8'.
On Unix, the encoding is the locale encoding.
On Windows, the encoding may be 'utf-8' or 'mbcs', depending on user
configuration.
Changed in version 3.6: Windows is no longer guaranteed to return
'mbcs'. See PEP 529 and [_enablelegacywindowsfsencoding()][4] for more
information.
Changed in version 3.7: Return ‘utf-8’ in the UTF-8 mode.
def _playsoundWin(sound, block = True):
from ctypes import c_buffer, windll
from random import random
from time import sleep
def winCommand(*command):
buf = c_buffer(255)
command = ' '.join(command)
# errorCode = int(windll.winmm.mciSendStringA(command, buf, 254, 0)) # original line
errorCode = int(windll.winmm.mciSendStringW(command, buf, 254, 0))
if errorCode:
errorBuffer = c_buffer(255)
# windll.winmm.mciGetErrorStringA(errorCode, errorBuffer, 254) # original line
windll.winmm.mciGetErrorStringW(errorCode, errorBuffer, 254)
exceptionMessage = ('\n Error ' + str(errorCode) + ' for command:'
'\n ' + command +
'\n ' + errorBuffer.value)
raise PlaysoundException(exceptionMessage)
return buf.value
alias = 'playsound_' + str(random())
winCommand('open "' + sound + '" alias', alias)
# winCommand('set', alias, 'time format milliseconds') # is not needed
# durationInMS = winCommand('status', alias, 'length') # returns bytes!
# durationInMS = durationInMS.decode() # needed for the original command
# winCommand('play', alias, 'from 0 to', durationInMS)
winCommand('play', alias, 'wait') # 'wait' does the trick
if block:
pass
# sleep(float(durationInMS) / 1000.0) # don't know it's purpose