Python findall、正则表达式、unicode
Python findall, regex, unicode
我正在尝试编写一个 Python 脚本来搜索目录树并列出所有 .flac 文件并从 resp 派生艺术家、专辑和标题。 dir/subdir/filename 并将其写入文件。该代码工作正常,直到它遇到一个 unicode 字符。这是代码:
import os, glob, re
def scandirs(path):
for currentFile in glob.glob(os.path.join(path, '*')):
if os.path.isdir(currentFile):
scandirs(currentFile)
if os.path.splitext(currentFile)[1] == ".flac":
rpath = os.path.relpath(currentFile)
print "**DEBUG** rpath =", rpath
title = os.path.basename(currentFile)
title = re.findall(u'\d\d\s(.*).flac', title, re.U)
title = title[0].decode("utf8")
print "**DEBUG** title =", title
fpath = os.path.split(os.path.dirname(currentFile))
artist = fpath[0][2:]
print "**DEBUG** artist =", artist
album = fpath[1]
print "**DEBUG** album =", album
out = "%s | %s | %s | %s\n" % (rpath, artist, album, title)
flist = open('filelist.tmp', 'a')
flist.write(out)
flist.close()
scandirs('./')
代码输出:
**DEBUG** rpath = Thriftworks/Fader/Thriftworks - Fader - 01 180°.flac
**DEBUG** title = 180°
**DEBUG** artist = Thriftworks
**DEBUG** album = Fader
Traceback (most recent call last):
File "decflac.py", line 25, in <module>
scandirs('./')
File "decflac.py", line 7, in scandirs
scandirs(currentFile)
File "decflac.py", line 7, in scandirs
scandirs(currentFile)
File "decflac.py", line 20, in scandirs
out = "%s | %s | %s | %s\n" % (rpath, artist, album, title)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 46: ordinal not in range(128)
但是在 Python 控制台中尝试时,它工作正常:
>>> import re
>>> title = "Thriftworks - Fader - 01 180°.flac"
>>> title2 = "dummy"
>>> title = re.findall(u'\d\d\s(.*).flac', title, re.U)
>>> title = title[0].decode("utf8")
>>> out = "%s | %s\n" % (title2, title)
>>> print out
dummy | 180°
所以,我的问题是:
1)为什么相同的代码在控制台中有效,但在脚本中却无效?
2) 如何修复脚本?
Python 控制台与您的终端一起工作,并根据其语言环境解释 unicode 编码。
用新的str.format
替换行:
out = u"{} | {} | {} | {}\n".format(rpath, artist, album, title)
并在写入文件时编码为 utf8:
with open('filelist.tmp', 'a') as f:
f.write(out.encode('utf8'))
或import codecs
直接做:
with codecs.open('filelist.tmp', 'a', encoding='utf8') as f:
f.write(out)
或者,因为 utf8 是默认值:
with open('filelist.tmp', 'a') as f:
f.write(out)
在控制台中,您的终端设置定义了编码。如今,这主要是 unicode 上的 Unicode,例如Linux/BSD/MacOS 和 Windows-1252 Windows。在解释器中,它默认为 python 文件的编码,通常是 ascii(除非你的代码以 UTF Byte-Order-Mark 开头)。
我不太确定,但也许可以在字符串“%s | %s | %s | %s\n”前加上 u
前缀使其成为unicode 字符串可以提供帮助。
通过切换到 Python3 解决,它按预期处理 unicode 案例。
替换:
title = title[0].decode("utf8")
用于:
title = title[0]
甚至不需要在 'out' 的值前加上 'u' 前缀或在写入时指定编码。
我爱 Python3.
将 glob
用于包含 Unicode 字符的文件名时,请使用 Unicode 字符串作为模式。这使得 glob
return Unicode 字符串而不是字节字符串。打印 Unicode 字符串会在输出时自动将它们编码为控制台的编码。如果您的歌曲包含控制台编码不支持的字符,您仍然会遇到问题。在这种情况下,将数据写入 UTF-8 编码的文件并在支持 UTF-8 的编辑器中查看它。
>>> import glob
>>> for f in glob.glob('*'): print f
...
ThriftworksFaderThriftworks - Fader - 01 180░.flac
>>> for f in glob.glob(u'*'): print f
...
ThriftworksFaderThriftworks - Fader - 01 180°.flac
这也适用于 os.walk
,并且是进行递归搜索的更简单方法:
#!python2
import os, fnmatch
def scandirs(path):
for path,dirs,files in os.walk(path):
for f in files:
if fnmatch.fnmatch(f,u'*.flac'):
album,artist,tracktitle = f.split(u' - ')
print 'Album: ',album
print 'Artist:',artist
title,track = tracktitle.split(u' ',1)
track = track[:-5]
print 'Track: ',track
print 'Title: ',title
scandirs(u'.')
输出:
Album: ThriftworksFaderThriftworks
Artist: Fader
Track: 180°
Title: 01
我正在尝试编写一个 Python 脚本来搜索目录树并列出所有 .flac 文件并从 resp 派生艺术家、专辑和标题。 dir/subdir/filename 并将其写入文件。该代码工作正常,直到它遇到一个 unicode 字符。这是代码:
import os, glob, re
def scandirs(path):
for currentFile in glob.glob(os.path.join(path, '*')):
if os.path.isdir(currentFile):
scandirs(currentFile)
if os.path.splitext(currentFile)[1] == ".flac":
rpath = os.path.relpath(currentFile)
print "**DEBUG** rpath =", rpath
title = os.path.basename(currentFile)
title = re.findall(u'\d\d\s(.*).flac', title, re.U)
title = title[0].decode("utf8")
print "**DEBUG** title =", title
fpath = os.path.split(os.path.dirname(currentFile))
artist = fpath[0][2:]
print "**DEBUG** artist =", artist
album = fpath[1]
print "**DEBUG** album =", album
out = "%s | %s | %s | %s\n" % (rpath, artist, album, title)
flist = open('filelist.tmp', 'a')
flist.write(out)
flist.close()
scandirs('./')
代码输出:
**DEBUG** rpath = Thriftworks/Fader/Thriftworks - Fader - 01 180°.flac
**DEBUG** title = 180°
**DEBUG** artist = Thriftworks
**DEBUG** album = Fader
Traceback (most recent call last):
File "decflac.py", line 25, in <module>
scandirs('./')
File "decflac.py", line 7, in scandirs
scandirs(currentFile)
File "decflac.py", line 7, in scandirs
scandirs(currentFile)
File "decflac.py", line 20, in scandirs
out = "%s | %s | %s | %s\n" % (rpath, artist, album, title)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 46: ordinal not in range(128)
但是在 Python 控制台中尝试时,它工作正常:
>>> import re
>>> title = "Thriftworks - Fader - 01 180°.flac"
>>> title2 = "dummy"
>>> title = re.findall(u'\d\d\s(.*).flac', title, re.U)
>>> title = title[0].decode("utf8")
>>> out = "%s | %s\n" % (title2, title)
>>> print out
dummy | 180°
所以,我的问题是: 1)为什么相同的代码在控制台中有效,但在脚本中却无效? 2) 如何修复脚本?
Python 控制台与您的终端一起工作,并根据其语言环境解释 unicode 编码。
用新的str.format
替换行:
out = u"{} | {} | {} | {}\n".format(rpath, artist, album, title)
并在写入文件时编码为 utf8:
with open('filelist.tmp', 'a') as f:
f.write(out.encode('utf8'))
或import codecs
直接做:
with codecs.open('filelist.tmp', 'a', encoding='utf8') as f:
f.write(out)
或者,因为 utf8 是默认值:
with open('filelist.tmp', 'a') as f:
f.write(out)
在控制台中,您的终端设置定义了编码。如今,这主要是 unicode 上的 Unicode,例如Linux/BSD/MacOS 和 Windows-1252 Windows。在解释器中,它默认为 python 文件的编码,通常是 ascii(除非你的代码以 UTF Byte-Order-Mark 开头)。
我不太确定,但也许可以在字符串“%s | %s | %s | %s\n”前加上
u
前缀使其成为unicode 字符串可以提供帮助。
通过切换到 Python3 解决,它按预期处理 unicode 案例。
替换:
title = title[0].decode("utf8")
用于:
title = title[0]
甚至不需要在 'out' 的值前加上 'u' 前缀或在写入时指定编码。
我爱 Python3.
将 glob
用于包含 Unicode 字符的文件名时,请使用 Unicode 字符串作为模式。这使得 glob
return Unicode 字符串而不是字节字符串。打印 Unicode 字符串会在输出时自动将它们编码为控制台的编码。如果您的歌曲包含控制台编码不支持的字符,您仍然会遇到问题。在这种情况下,将数据写入 UTF-8 编码的文件并在支持 UTF-8 的编辑器中查看它。
>>> import glob
>>> for f in glob.glob('*'): print f
...
ThriftworksFaderThriftworks - Fader - 01 180░.flac
>>> for f in glob.glob(u'*'): print f
...
ThriftworksFaderThriftworks - Fader - 01 180°.flac
这也适用于 os.walk
,并且是进行递归搜索的更简单方法:
#!python2
import os, fnmatch
def scandirs(path):
for path,dirs,files in os.walk(path):
for f in files:
if fnmatch.fnmatch(f,u'*.flac'):
album,artist,tracktitle = f.split(u' - ')
print 'Album: ',album
print 'Artist:',artist
title,track = tracktitle.split(u' ',1)
track = track[:-5]
print 'Track: ',track
print 'Title: ',title
scandirs(u'.')
输出:
Album: ThriftworksFaderThriftworks
Artist: Fader
Track: 180°
Title: 01