python音标是什么_python转换工具之汉语拼音与国际音标的实现
#!/usr/bin/env python
# This file has following encoding: utf-8
######################## 模塊導入 ########################
import os, re
######################## 全局變量 ########################
# 三種字符集標志
GB18030, GBK, UTF8 = "gb18030", "gbk", "utf8"
# 字符編碼頁解碼失敗標志
decodingFailed = False # 初始狀態:關閉
# 正則表達式替換命令元組和內部標志
cmdPairTuple = tuple() # 預備空對象
PATTERN, SUBST = 0, 1 # 匹配段和替換段
# 經過編譯的正則表達式對象列表
reList = [] # 預備空對象
# 創建正則表達式替換命令元組的默認設置表(固定集合對象)
defaultPrefSet = frozenset([
### 以下各行字符串,凡行首用#號注釋者均表示無效;
### 凡行首未用#號注釋者均有效,效用如后面注釋所述:
# "NUMBER_2_BY_AR4", # 數字“二”有大開口度韻腹
# "AI_INC_NEAR_OPEN_FRONT", # ai/uai韻腹為舌面前次開元音
# "AIR_ANR_INC_NEAR_OPEN_CENTRAL", # air/anr韻腹為舌面央次低元音
# "CENTRAL_A_BY_SMALLCAPS_A", # “央a”采用小型大寫[A]標明
# "IE_YUE_INC_SMALLCAPS_E", # ie/yue采用小型大寫[E]標明
# "IE_YUE_INC_E", # ie/yue采用[e]標明(覆蓋上一條)
# "IAN_YUAN_AS_AN", # ian/yuan韻腹和an一樣
# "ONLY_YUAN_AS_AN", # 僅yuan韻腹和an一樣(覆蓋上一條)
# "OU_INC_SCHWA", # ou/iou采用舌面央中元音韻腹
# "IONG_BY_IUNG", # iong韻母采用i韻頭u韻腹
# "ASPIRATE_BY_TURNED_COMMA", # 采用反逗號弱送氣符號
# "RHOTICITY_BY_RHOTIC_HOOK", # 兒化韻卷舌動作采用卷舌小鉤
# "ONLY_ER_BY_RHOTIC_HOOK", # 只有er音節卷舌動作采用卷舌小鉤
# "INITIAL_R_BY_VED_RETRO_FRIC", # 聲母r為卷舌濁擦音而非卷舌通音
# "R_TURNED_WITH_HOOK", # 嚴格采用卷舌通音符號
# "TRANSITIONAL_SCHWA_IN_ING", # ing有舌面央中元音韻腹
# "TRANSITIONAL_SCHWA_IN_UEN", # 合口un有舌面央中元音韻腹
# "NO_TRANSITIONAL_U", # bo/po/mo/fo沒有[u]韻頭
# "SYLLABLE_JUNCTURE_BY_PLUS", # 音節間斷采用開音渡+號而非.號
# "HTML_SUP_TAG_FOR_TONE_VALUE", # 調值采用HTML上標標簽格式
# "HIDE_ALL_TONE_VALUE", # 隱藏所有聲調轉換
### 以下選項僅存設想,目前尚未實現:
# "RETROFLEX_INITIAL_STANDALONE", # 卷舌聲母可成音節而無需舌尖元音
# "ZERO_INITIAL_HAS_CONSONANT", # 零聲母有輔音
])
# 正則表達式替換命令元組一攬子創建設置方案(元組,[0]位為說明)
recipeLinWang1992 = ( U"林燾、王理嘉《語音學教程》",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "AI_INC_NEAR_OPEN_FRONT"
)
recipeBeidaCN2004 = ( U"北京大學中文系《現代漢語》(重排本)",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "INITIAL_R_BY_VED_RETRO_FRIC",
"TRANSITIONAL_SCHWA_IN_UEN", "IONG_BY_IUNG", "IAN_YUAN_AS_AN"
)
recipeHuangLiao2002 = (U"黃伯榮、廖序東《現代漢語》(增訂三版)",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "CENTRAL_A_BY_SMALLCAPS_A",
"TRANSITIONAL_SCHWA_IN_UEN", "ONLY_YUAN_AS_AN", "ONLY_ER_BY_RHOTIC_HOOK",
"INITIAL_R_BY_VED_RETRO_FRIC"
)
recipeYangZhou1995 = ( U"楊潤陸、周一民《現代漢語》(北師大文學院教材)",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "TRANSITIONAL_SCHWA_IN_UEN",
"INITIAL_R_BY_VED_RETRO_FRIC"
)
recipeYuan2001 = ( U"袁家驊等《漢語方言概要》(第二版重排)",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "INITIAL_R_BY_VED_RETRO_FRIC",
"ONLY_ER_BY_RHOTIC_HOOK", "IAN_YUAN_AS_AN", "TRANSITIONAL_SCHWA_IN_UEN",
"IE_YUE_INC_E"
)
recipeTang2002 = ( U"唐作藩《音韻學教程》(第三版)",
"NO_TRANSITIONAL_U", "ASPIRATE_BY_TURNED_COMMA", "INITIAL_R_BY_VED_RETRO_FRIC",
"ONLY_ER_BY_RHOTIC_HOOK", "IAN_YUAN_AS_AN", "TRANSITIONAL_SCHWA_IN_UEN",
"IE_YUE_INC_E", "OU_INC_SCHWA"
)
#############www.iplaypy.com 函數聲明 ########################
def createCmdPairTuple(prefSet = defaultPrefSet):
U"""創建正則表達式替換命令元組
然后編譯便于反復使用的匹配段正則表達式對象列表
參數prefSet是一個控制命令元組創建的選項設置序列"""
### 預先處理同系列設置的覆蓋關系——defaultPrefSet也可能讓人動了手腳
prefSet = set(prefSet) # 先換為可變集合副本,以防固定類型參數
if "IE_YUE_INC_E" in prefSet and "IE_YUE_INC_SMALLCAPS_E" in prefSet:
prefSet.remove("IE_YUE_INC_SMALLCAPS_E")
if "ONLY_YUAN_AS_AN" in prefSet and "IAN_YUAN_AS_AN" in prefSet:
prefSet.remove("IAN_YUAN_AS_AN")
global cmdPairTuple
cmdPairTuple = (
### 轉換聲母前的預處理
# 音節間斷與隔音符號
(UR"([aoeiuvüê][1-5]?)([yw])", # a/o/e前有元音時必須寫隔音符號
UR"1'2"), # 標明不必寫出隔音符號的音節間斷
(UR"'", (UR"+" if "SYLLABLE_JUNCTURE_BY_PLUS" in prefSet else
UR".")), # 音節間斷(開音渡)標記
# 兼容正規的印刷體字母ɡ/ɑ->g/a
(UR"ɡ", UR"g"),
(UR"ɑ", UR"a"),
# 特殊的ê韻母,只能搭配零聲母(“誒”字等)
(UR"(ê|ea)", UR"?"), # ea是ê的GF 3006表示
# 消除因可以緊鄰韻腹充當聲母或韻尾的輔音的歧義
(UR"r([aoeiu])", UR"R1"), # 聲母r暫改為R,以免與卷舌標志r混淆
(UR"n([aoeiuvü])", UR"N1"), # 聲母n暫改為N,以免與韻尾n/ng混淆
# 需要排除式匹配轉換的韻母
(UR"ng(?![aeu])", UR"?"), # 雙字母ng,后鼻音韻尾或自成音節
(UR"(?
UR"?"), # 單韻母e,此前已轉換ea和聲母r/n
(UR"(?
(UR"ar4" if "NUMBER_2_BY_AR4" in prefSet else
UR"er4")), # 數字“二”是否有大開口度韻腹
(UR"(?
(UR"a?4" if "ONLY_ER_BY_RHOTIC_HOOK" in prefSet else
UR"ar4")), # 數字“二”也屬于er音節,可特別選用小鉤
(UR"a(?![ion?])", (UR"?" if "CENTRAL_A_BY_SMALLCAPS_A" in prefSet else
UR"a")), # “央a”是否用小型大寫[A]標明,已轉換“二”
(UR"(?
(UR"??" if "ONLY_ER_BY_RHOTIC_HOOK" in prefSet else
UR"?r")), # 一般的卷舌單韻母er,此前已排除“二”
(UR"(?
(UR"(?<=[bpmf])o(?![u?])",
(UR"o" if "NO_TRANSITIONAL_U" in prefSet else
UR"uo")), # bo/po/mo/fo是否有韻頭u
### 聲母——無需轉換m/f/n/l/s/r(但r可根據設置執行轉換)
# 送氣清輔音聲母
(UR"([ptk])", UR"1?"),
(UR"q", UR"t??"),
(UR"(ch|?)", UR"t??"), # 后者是ch的注音變體
(UR"c", UR"ts?"), # 此前已排除ch
# 不送氣清輔音聲母
(UR"b", UR"p"), # 此前已排除送氣的p/t/k
(UR"d", UR"t"),
(UR"g", UR"k"), # 此前已排除后鼻音雙字母中的g,注意隔音
(UR"j", UR"t?"),
(UR"(zh|?)", UR"t?"), # 后者是zh的注音變體
(UR"z", UR"ts"), # 此前已排除zh
# 擦音聲母
(UR"(sh|?)", UR"?"), # 后者是sh的注音變體
(UR"x", UR"?"), # 聲母x,排除后再轉換h
(UR"h", UR"x"), # 聲母h,此前已排除zh/ch/sh
### 韻母
# 舌尖元音韻母
(UR"(s??)i", UR"1?"), # zi/ci/si
(UR"([?R]??)i", UR"1?"), # zhi/chi/shi/ri
# 部分韻腹省略表示的韻母+隔音符號和韻頭w/y
(UR"iu", UR"iou"), # 無需轉換iou
(UR"ui", UR"uei"), # 無需轉換uei
(UR"wu?", UR"u"),
(UR"yi?", UR"i"), # 此前已排除iu
# 韻頭[i]/[y]的韻母
(UR"iu|[üv]", UR"y"), # 轉換ü/v,恢復yu/yue,準備yuan/yun
(UR"ian", (UR"ian" if "IAN_YUAN_AS_AN" in prefSet else
UR"i?n")), # 是否認為ian韻腹和an一樣
(UR"yan", (UR"yan" if ("ONLY_YUAN_AS_AN" in prefSet)
or ("IAN_YUAN_AS_AN" in prefSet) else
UR"y?n")), # 是否認為yuan韻腹和an一樣(覆蓋上一選項)
(UR"(???)uan", (UR"
2964
1yan" if ("ONLY_YUAN_AS_AN" in prefSet)
or ("IAN_YUAN_AS_AN" in prefSet) else
UR"1y?n")), # {j/q/x}uan,是否認為和an一樣
(UR"(???)u", UR"1y"), # {j/q/x}u{e/n}韻頭,此前已排除{j/q/x}uan
(UR"([iy])e(?!n)", (UR"1?" if "IE_YUE_INC_SMALLCAPS_E" in prefSet else
UR"1e")), # ie/yue/üe/ve,此前已轉換{j/q/x}u
(UR"([iy])e(?!n)", (UR"1e" if "IE_YUE_INC_E" in prefSet else
UR"1?")), # ie/yue是否采用[e]標明,此前已判斷[E]
# 舌面央中元音輕微過渡韻腹
(UR"i?", (UR"i??" if "TRANSITIONAL_SCHWA_IN_ING" in prefSet else
UR"i?")), # ing是否有舌面央中元音韻腹
(UR"(un|uen)", (UR"u?n" if "TRANSITIONAL_SCHWA_IN_UEN" in prefSet else
UR"un")), # 合口un/uen過渡,此前已排除撮口[j/q/x]un
# 后移的a
(UR"ao", UR"ɑu"), # 包括ao/iao,o改為u
(UR"a?", UR"ɑ?"), # 包括ang/iang/uang
# 韻母en/eng韻腹是舌面央中元音
(UR"e([n?])", UR"?1"),
# ong類韻母
(UR"io?", (UR"iu?" if "IONG_BY_IUNG" in prefSet else
UR"y?")), # iong的兩種轉換,此前yong已轉換為iong
(UR"o?", UR"u?"), # ong,此前已排除iong
### 兒化音變——無需轉換ar/ir/ur/aur/our/yur
# 舌尖元音韻母
(UR"[??]r", UR"?r"), # {zh/ch/sh/r/z/c/s}ir
# 鼻韻尾脫落和相應的韻腹元音替換
(UR"[a?][in]r",(UR"?r" if "AIR_ANR_INC_NEAR_OPEN_CENTRAL" in prefSet else
UR"ar")), # air/anr韻尾脫落后的韻腹替換
(UR"eir|?nr", UR"?r"), # eir韻腹央化,韻尾脫落;enr韻尾脫落
(UR"([iy])r", UR"1?r"), # ir/yr增加央化韻腹
(UR"([iuy])nr", UR"1?r"), # inr/ynr/unr韻尾脫落后增加央化韻腹
(UR"iu?r", UR"iu?r"), # iungr(iongr的可選變換)
(UR"([iuy])?r", UR"1??r"), # ingr/yngr/ungr韻尾脫落后增加央化鼻化韻腹
(UR"?r", UR"?r"), # ang/eng韻尾兒化脫落后韻腹鼻化
### 聲母、韻母轉換的善后掃尾工作
# 處理兒化韻卷舌動作
(UR"r", (UR"?" if "RHOTICITY_BY_RHOTIC_HOOK" in prefSet else
UR"r")), # 是否先把兒化韻卷舌動作改為卷舌小鉤
(UR"R", (UR"?" if "INITIAL_R_BY_VED_RETRO_FRIC" in prefSet else
UR"r")), # 恢復聲母r,是否采用卷舌濁擦音表示聲母r
# 此前已處理完卷舌動作和聲母,現在處理剩下的r字符的可選轉換
(UR"r", (UR"?" if "R_TURNED_WITH_HOOK" in prefSet else
UR"r")), # 是否嚴格采用卷舌通音符號[?]
# 恢復聲母n
(UR"N", UR"n"), # 此前已處理完單元音韻母e和ie/yue
# 其他選項
(UR"?", (UR"?" if "ASPIRATE_BY_TURNED_COMMA" in prefSet else
UR"?")), # 是否采用反逗號送氣符號
(UR"ai", (UR"?i" if "AI_INC_NEAR_OPEN_FRONT" in prefSet else
UR"ai")), # (非兒化的)ai/uai韻腹為舌面前次開元音
(UR"ou", (UR"?u" if "OU_INC_SCHWA" in prefSet else
UR"ou")), # ou/iou是否采用舌面央中元音韻腹
### 聲調
# 先期處理
((UR"[1-5]" if "HIDE_ALL_TONE_VALUE" in prefSet else
UR"5"), UR""), # 只隱藏輕聲還是隱藏所有的聲調轉換
(UR"([1-4])",
(UR"1" if "HTML_SUP_TAG_FOR_TONE_VALUE" in prefSet else
UR"(1)")), # 隔離單個數字調號
# 標出普通話調值
("([(>])1([)<])", UR"1 552"), # 陰平(第一聲)
("([(>])2([)<])", UR"1 352"), # 陽平(第二聲)
("([(>])3([)<])", UR"1 2142"), # 上聲(第三聲)
("([(>])4([)<])", UR"1 512"), # 去聲(第四聲)
("([(>]) ([235])",UR"12") # 去掉此前標調值時加上的空格
)
### 以上,替換命令元組創建完成!
# 編譯正則表達式對象,以便反復使用
global reList
reList = map(re.compile, [pair[PATTERN] for pair in cmdPairTuple])
def decodeLine(encodedLine):
U"""對每一行拼音字符串做字符編碼頁解碼"""
try:
decodedLine = encodedLine.decode(UTF8)
except UnicodeDecodeError: # 如果不是UTF-8
try:
decodedLine = encodedLine.decode(GB18030)
except UnicodeDecodeError: # 如果GB-18030也不行
decodedLine = "" + os.linesep # 解碼失敗,只能清空
global decodingFailed
decodingFailed = True # 設置字符編碼頁解碼失敗標志
except UnicodeEncodeError: # wx中可能出現編碼錯誤
decodedLine = encodedLine
return decodedLine
def msgOnDecodingFailure(fileName = "標準輸入流"):
U"""針對字符編碼頁解碼失敗的文件在事后通過標準錯誤流提出警告"""
global decodingFailed
if decodingFailed: # 檢查上次文件處理中是否出現解碼錯誤
sys.stderr.write((U"%s警告:%s解碼失敗!"%(sys.argv[0], fileName)).encode(GBK) + os.linesep)
decodingFailed = False # 重置字符集碼頁解碼失敗標志為關閉
def convertLine(pinyinLine):
U"""對每一行拼音字符串依次執行全部替換命令,像流編輯器sed一樣工作"""
# 以單個“#”開頭的行不轉換,當作注釋行
if pinyinLine.startswith("#") and not pinyinLine.startswith("##"):
return pinyinLine[1:] # 去掉開頭的“#”后再返回
# 以兩個“#”開頭的行,只保留一個“#”,然后繼續
if pinyinLine.startswith("##"):
pinyinLine = pinyinLine[1:]
ipaLine = pinyinLine.lower() # 大寫字母在替換過程中另有意義
for eachRe, eachCmdPair in zip(reList, cmdPairTuple):
ipaLine = eachRe.sub(eachCmdPair[SUBST], ipaLine)
return ipaLine
def convertPinyin2IPA(pinyinLines, linesep=""):
U"""將漢語拼音文稿轉換為國際音標文稿
參數pinyinLines是輸入的字符串序列
參數linesep是行分隔符(對于fp.readlines()或s.splitlines(True)的輸入,缺省即可)"""
# 逐行處理解碼和轉換,有利于減少解碼帶來的亂碼行
ipaLines = map(convertLine, map(decodeLine, pinyinLines))
return linesep.join(ipaLines).encode(UTF8) # 必須按UTF-8再encode一下
######################## 主干函數 ########################
def Pinyin2IPA(pinyinLines, *prefs):
U"""創建轉換命令,并將漢語拼音文稿轉換為國際音標文稿
參數pinyinLines可以是字符串序列或單個字符串(后者也會包裝進元組)
參數收集元組prefs是一個控制命令元組創建的選項設置表"""
# 根據設置表創建替換命令元組(設置表缺省時提供默認值)
if not prefs:
prefs = defaultPrefSet
createCmdPairTuple(prefs)
# 將單個字符串包裝進元組,以便逐行處理
#www.iplaypy.com
if isinstance(pinyinLines, str):
pinyinLines = (pinyinLines, )
return convertPinyin2IPA(pinyinLines)
######################## 直接運行 ########################
if __name__ == '__main__':
import glob, locale, sys
globFailMsg = U"%s錯誤:參數“%s”不能匹配任何有效的文件名!".encode(GBK) + os.linesep
readFailMsg = U"%s錯誤:文件“%s”數據讀取失敗!".encode(GBK) + os.linesep
if len(sys.argv) > 1:
if sys.argv[1].lower() not in ("/?", "/h", "--help", "-h"):
for eachArg in sys.argv[1:]: # 遍歷glob表達式參數
fileNameList = glob.glob(eachArg) # 考慮DOS不負責glob解析
if not fileNameList:
sys.stderr.write(globFailMsg%(sys.argv[0], eachArg))
else:
for eachFileName in fileNameList:
try:
sys.stdout.write(Pinyin2IPA(open(eachFileName, 'r').readlines()))
msgOnDecodingFailure(U"文件“%s”"%eachFileName)
except IOError:
sys.stderr.write(readFailMsg%(sys.argv[0], eachFileName))
else: # 按照本地設置的編碼方式輸出模塊文檔作為簡單幫助
language_dummy, encoding = locale.getdefaultlocale()
print (__doc__%(sys.argv[0], sys.argv[0])).encode(encoding)
else:
sys.stdout.write(Pinyin2IPA(sys.stdin.readlines()))
msgOnDecodingFailure()
######################## 腳本結束 ########################
總結
以上是生活随笔為你收集整理的python音标是什么_python转换工具之汉语拼音与国际音标的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大学生计算机面试,大学生计算机毕业面试自
- 下一篇: 测试网线是否正常的方法有哪些?