我编写了一个程序,可以帮助我在歌曲的歌词之间快速切换。它从文件中读取歌词.lyr
并将它们打印给我。
这是一个简化版本,没有任何附加功能,如 edit_line()
.此代码仍然出现问题。
import os
class Lyrics:
def __init__(self, file):
'''Initialize new Lyrics object'''
self.file = file.replace("/", "\")
self.path = self.file.rsplit("\", 1)[0] + "\"
self.suffix = "." + self.file.rsplit(".")[-2]
self.name = self.file
.replace(self.path, "")
.replace(".lyr", "")
.replace(self.suffix, "")
def draw(self):
'''Draw lyrics on user's screen'''
maxlen = len(str(len(self.content)))
print("[[ %s ]]"%self.name)
for i,line in enumerate(self.content):
print("%i %s"%(i+1, line), end="")
def play(self):
'''View lyrics'''
with open(self.file, "r") as f:
self.content = f.readlines()
#os.system("cls")
self.draw()
input("[[ Press enter to quit ... ]]")
def main(directory):
# Get lyric files from directory
lyric_files = []
for file in os.listdir(directory):
if file.endswith(".lyr"):
lyric_files.append(Lyrics(directory + file))
# Create variable for showing messages to user
msg = ""
# Main loop
while True:
# Print lyric files
#os.system("cls")
for i, file in enumerate(lyric_files):
print("%i :: %s"%(i+1, file.name))
# Handle input
cmd = input("%s>"%msg)
if cmd == "bye":
break
try:
lyric_files[int(cmd)-1].play()
msg = ""
except ValueError:
msg = "ValueError: Input must be an integern"
except IndexError:
msg = "IndexError: Integer must be between 1 and %in"%len(lyric_files)
if __name__ == "__main__":
main("E:\documents\lyrics\")
E:documentslyrics
中的文件使用以下格式命名:
Artist - Song.format.lyr`
例如:
E:documentslyricsAdele - Set Fire to the Rain.mp3.lyr
当我打开程序时,它会按预期列出所有文件,并在以下之后要求我输入:
1 :: Adele - Set Fire to the Rain
2 :: Eminem - Not Afraid
3 :: Nicki Minaj - Starships
>
当我用索引1
打开Set Fire to the Rain
的歌词时,它们会完美地打开。但是,当我尝试打开歌词时 Not Afraid
,我可以在输出中看到大约 50 行歌词,而歌词文件实际上大约有 120 行长。然后它要求我输入来自main()
函数的输入,ValueError
如下所示:
1 first_line_in_lyrics
2 second_line_in_lyrics
i ...
42 fourty_second_line_in_lyrics
43 fourty_third_line_in_lyrics
1 :: Adele - Set Fire to the Rain
2 :: Eminem - Not Afraid
3 :: Nicki Minaj - Starships
ValueError: Input must be an integer
>
这些文件彼此几乎相同(当然歌词是不同的)。该程序在 IDLE 上运行良好,但在 python 命令行上则不然。
你说你编写了一个程序:
它从.lyr文件中读取歌词并将它们打印给我
但是我对你的程序的阅读:
def get_lyric_files(path):
lyric_files = []
for lyrics in os.listdir(path):
if lyrics[:-4].split(".")[-1] in ("wav", "mp3"):
lyric_files .append(Lyrics(path + lyrics))
return lyric_files
看起来您从.mp3和.wav文件中获取歌词。一些mp3文件包含歌词标签,但你不解析它们。也许你打算:
lyric_files .append(Lyrics(path + lyrics + '.lyr'))
开始编辑
我现在看到我误读了这一行:
if lyrics[:-4].split(".")[-1] in ("wav", "mp3"):
我以为是:
if lyrics[-4:].split(".")[-1] in ("wav", "mp3"):
此代码与 *.mp3.???
匹配。如果您只查找 .lyr 文件,为什么不:
if lyrics[-8:] in (".wav.lyr", ".mp3.lyr"):
编辑 2
另外,这不好:
try:
lyrics[int(cmd)-1].play()
except ValueError:
pass
except IndexError:
pass
你真的想在.play()中捕获并忽略ValueError和IndexError吗?相反:
try:
lyric = lyrics[int(cmd)-1]
except ValueError:
print 'You must enter a number'
except IndexError:
print 'You must enter a number between 1 and', len(lyrics)
else:
lyric.play()
如果问题正在运行,这可能有助于您找到问题,因为try
不会屏蔽任何错误。
结束编辑
否则,如果您想从.mp3文件中读取歌词,您可以使用像mutagen这样的库
import mutagen, mutagen.mp3, mutagen.easyid3
# . . .
mp3Tags = mutagen.mp3.MP3(mp3FileName)
lyricFrame = mp3Tags.get("USLT::'eng'")
if lyricFrame:
lyricText = lyricFrame.text
lyrics = lyricText.split('n')
这个问题看起来很奇怪,但并非不可能。以下是我们目前得到的:
- 由于文件确实打开并且其中一些被打印出来,因此问题一定出在文件的打印上。
- 我三次检查了您的代码,问题不在于您的
draw()
方法。 - 由于问题仅发生在某些文件上,而不会出现在其他文件中,因此问题可能出在文件本身上。
- 由于问题只发生在python命令行而不是IDLE上:问题必须在于打印某些文件的某些内容,这些内容可以在IDLE中打印,但不能在python命令行中打印。
如果您确定您的绘制函数看起来像这样(我花了一段时间才弄清楚maxlen
的事情):
def draw(self):
'''Draw lyrics on user's screen'''
maxlen = len(str(len(self.content)))
print("[[ %s ]]"%self.name)
for i,line in enumerate(self.content):
print("%i %s"%(i+1, line), end="")
我们只剩下这样一个事实,即self.content
和/或文件内容本身有问题。
简而言之:我 99% 确定您的文件中有一些字符可以通过 IDLE 打印,但不能通过 python 命令行打印。这些字符可以是任何东西:%
、'
、"
、´
、|
、#
,甚至是一些不可见的字符,如果不用箭头键滚动浏览它们,你就看不到它们。
如果你能发布你的歌词内容,我可以尝试提供更多帮助。尤其是最后打印的行,以及根本不打印的第一行。