您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Python 3.x踩坑的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Python 3.x踩坑的示例分析”這篇文章吧。
# 我們打開文件使用 open 方法 xml = open("demo.xml") # 使用 open 命令讀取文件時,經(jīng)常會出現(xiàn)下列錯誤 Traceback (most recent call last): File "TempConvert.py", line 84, in <module> for line in xml: UnicodeDecodeError: 'gbk' codec can't decode byte 0x8d in position 38: illegal multibyte sequence
# 出現(xiàn)這個錯誤的原因是系統(tǒng)默認(rèn)打開的編碼方式和文件不一致,需要通過帶格式參數(shù)的方式打開 # 比如,文件如果是 utf-8 格式文件,則需要采用下列格式參數(shù): xml = open("demo.xml", encoding="utf-8")
首先提出一個問題,使用正則表達(dá)式獲取到字符串中的郵箱列表。 例:A message from csev@umich.edu to cwen@iupui.edu about meeting @2PM
# 我們可以通過一個簡單的正則表達(dá)式,這里不考慮其他復(fù)雜條件 import re str = 'A message from csev@umich.edu to cwen@iupui.edu about meeting @2PM' lst1 = re.findall('\S+@\S+', s) print(lst1) # ['csev@umich.edu', 'cwen@iupui.edu'] # 然而我們發(fā)現(xiàn),下列正則表達(dá)式也有同樣的結(jié)果 lst2 = re.findall('\\S+@\\S+', s) print(lst2)
這就比較奇怪了,因為在其他語言的正則表達(dá)式中,\S
和 \\S
代表的含義并不相同,\S
表示一個非空字符,而 \\S
表示匹配字符串 \S
,于是我們作下列嘗試:
'\S' == '\\S' # True len('\\S') # 2 len('\S') # 2
是不是驚呆了!于是我又嘗試
'\s' == '\\s' # True len('\\s') # 2 len('\s') # 2 '\n' == '\\n' # False len('\\n') # 2 len('\n') # 1
我們發(fā)現(xiàn) \s
和 \n
的情況并不相同,通過一番查詢,找到了下面的文章:
Python regex '\s' vs '\s'
文中提到
Don't confuse python-level string-escaping and regex-level string-escaping. Since s is not an escapable character at python-level, the interpreter understand a string like \s as the two characters \ and s. Replace s with n, and it understands it as the newline character.
不要混淆 Python 中的字符串轉(zhuǎn)義和正則表達(dá)式級別的字符串轉(zhuǎn)義。由于 s 在 Python 不是可轉(zhuǎn)義字符,解釋器將 \s 這樣的字符串理解為兩個字符 \ 和 s。將 s 替換為 n,它將其理解為換行符。
雖然沒有提及到更權(quán)威的說法,但是也反應(yīng)出了,如果是 \s
會被當(dāng)做是兩個字符,如果是 \\s
因為 \\
是可轉(zhuǎn)義字符,被當(dāng)做了 \
一個字符,\\s
也就被當(dāng)做了 \s
兩個字符。所以才會出現(xiàn)這種情況。
'\s' == '\\s' # True
在學(xué)習(xí)正則表達(dá)式匹配規(guī)則時候發(fā)現(xiàn),Python 正則匹配的方式和其他的稍有不同,比如上一條提到的 \S
與 \\S
的問題,然后還有下面的:
Python 的正則匹配是從頭匹配,舉個例子,如果我們要匹配一個字符串中的電話號碼
在 JS 中你可以用下列的正則匹配
// 使用 JS 的方式,我們可以有下列的寫法 '我的手機(jī)號碼是15900000000不要告訴別人,否則我就把你號碼是13900000000告訴別人'.match(/1[0-9]{10}/g) // (2) ['15900000000', '13900000000']
但是如果你把同樣的正則放到 Python 中則不那么好使
import re str = '我的手機(jī)號碼是15900000000不要告訴別人,否則我就把你號碼是13900000000告訴別人' # 錯誤的寫法 mah = re.match('1[0-9]{10}', str) print(mah) # None
因為 Python 的匹配 match
默認(rèn)是從開頭開始匹配的,而 1 并不一定是給定的字符串的首字母。
# 應(yīng)該使用另一個方法 findall 代替 mah = re.findall('1[0-9]{10}', str) print(mah) # ['15900000000', '13900000000']
從這一點可以看出,Python 的很多庫都提供用不同于其他語言的方法,作為其他語言轉(zhuǎn)學(xué) Python 的小伙伴要實際測試過方法或者熟知的情況下使用,而不應(yīng)該不加思考的定式思維,一廂情愿的覺得 Python 就和其他的語言一樣。
Python 中對庫或者方法的幫助查看可以用下列的方式進(jìn)行:
【可選】在命令行環(huán)境下輸入 python 即可進(jìn)入 Python 編譯環(huán)境
使用 dir(庫、對象)
的方式查看庫或者對象可以提供的方法
dir('字符串') # 查看字符串有哪些操作方法 import re dir(re) # 查看正則表達(dá)式庫有哪些操作方法
使用 help(庫、對象)
的方式查看庫或者對象的幫助信息
import re help(re) # 查看正則表達(dá)式庫的幫助文檔 dir(re.match) # 查看正則表達(dá)式的 `match` 的幫助信息
如果我們是想把幫助文檔寫入文本文件中,可以在 命令行中 使用命令:
# 將 re 庫的幫助信息到 html 文檔 python -m pydoc -w re # windows 下可以用下列方法輸出到文本文件 python -m pydoc re > d:\re.txt
更多關(guān)于 pydoc 的信息可以參考官方文檔 pydoc
一些教程上對字符串的 base64 編碼的方式是這樣的:
str = "this is string example....wow!!!"; print "Encoded String: " + str.encode('base64','strict') # 預(yù)計輸出結(jié)果 Encoded String: dGhpcyBpcyBzdHJpbmcgZXhhbXBsZS4uLi53b3chISE=
但是這個代碼卻會報錯:
LookupError: 'base64' is not a text encoding; use codecs.encode() to handle arbitrary codecs
據(jù)了解,這種錯誤的寫法其實是來源于 Python 2.x 的寫法,但是在 Python 3.x 中寫法發(fā)生了變化,字符串的 base64 正確編碼方式應(yīng)該是:
import base64 str = "this is string example....wow!!!" # 返回原字符串編碼為字節(jié)串對象的版本 strb = str.encode() base64b = base64.b64encode(strb) base64 = base64b.decode() print(base64)
在百度搜索了很多關(guān)于 Python 調(diào)用 C# 動態(tài)鏈接庫的方式,大多是如下代碼:
import clr # clr.FindAssembly('DotNetWithPython.dll') # dll在當(dāng)前目錄 clr.AddReferenceToFile('DotNetWithPython.dll') # dll在當(dāng)前目錄 from DotNetWithPython import * # 導(dǎo)入動態(tài)鏈接庫中的所有類 if __name__ == '__main__': mainapp = MainForm() # 初始化 MainForm 類對象
可惜啊,沒有能正常使用的,我也不清楚到底是哪里出了問題,為什么都沒有效果呢,難不成這些都是 Python 2.x 的用法嗎?(我學(xué)的是 Python 3.x)
作了如下思考:
python 的 clr 即 PythonNet,那么是否直接到 PythonNet 官方或者 github 上查找相關(guān)代碼呢?
于是搜索到了下列地址:pythonnet.github.io/按照里面給出的代碼逐個嘗試,首先是這個:
from System import String from System.Collections import *
我們發(fā)現(xiàn)會報錯:
Traceback (most recent call last):
File "d:/Temp/PythonProjects/Demos/DllDo.py", line 10, in <module>
from System import String
ModuleNotFoundError: No module named 'System'
我們嘗試把代碼修改為:
import clr from System import String from System.Collections import *
可以確定,我們對 .NET 相關(guān)類的調(diào)用必須要 import clr
我們繼續(xù)嘗試,當(dāng)嘗試到下列代碼時:
import clr from System.Drawing import Point p = Point(5, 5)
又報錯了:
d:/Temp/PythonProjects/Demos/DllDo.py:11: DeprecationWarning: The module was found, but not in a referenced namespace.
Implicit loading is deprecated. Please use clr.AddReference('System.Drawing').
from System.Drawing import Point
從給出的錯誤信息中,我們可以看出,我們需要對空間進(jìn)行引用:
import clr clr.AddReference('System.Drawing') from System.Drawing import Point p = Point(5, 5) print(p) # {X=5,Y=5}
到了這一步,我們基本確定 Python 調(diào)用 C# 是沒有問題的,那么如果才能調(diào)用自己定義的 dll 動態(tài)鏈接庫呢?我們嘗試按照前文系統(tǒng)類的引用方式:
import clr clr.AddReference('DotNetWithPython') from DotNetWithPython import MainForm mainapp = MainForm()
結(jié)果報錯:
Traceback (most recent call last):
File "d:/Temp/PythonProjects/Demos/DllDo.py", line 12, in <module>
from DotNetWithPython import MainForm
ModuleNotFoundError: No module named 'DotNetWithPython'
于是我又想:
clr 可以正常調(diào)用 .NET 本身提供的類對象,調(diào)用不到我的 自己寫的動態(tài)鏈接庫和 .NET 本身提供的差異在于不在系統(tǒng)環(huán)境中,自己的 dll 在當(dāng)前目錄或者其他目錄
于是我們使用 dir(clr)
確定了一下是否有什么方法可用
import clr dir(clr) # ['AddReference', 'FindAssembly', 'GetClrType', 'ListAssemblies', 'Microsoft', 'Python', 'System', '_AtExit', '__class__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_extras', 'clrModule', 'clrmethod', 'clrproperty', 'e__NativeCall', 'getPreload', 'setPreload']
我們發(fā)現(xiàn)了方法 FindAssembly
感覺很像,于是我們按照前文系統(tǒng)類的引用方式及這一句進(jìn)行測試:
import clr clr.FindAssembly('DotNetWithPython.dll') clr.AddReference('DotNetWithPython') from DotNetWithPython import MainForm mainapp = MainForm()
還是一樣的錯誤,我都要哭了,于是我只能到 PythonNet Github 的 issues 中尋找答案,發(fā)現(xiàn)提出這個問題的人很多,并且問題被鎖定在了 .net core、.net 5,而 .Net Framework 中沒有出現(xiàn)這種問題,我于是新建了一個基于 .Net Framework 4.x 的項目進(jìn)行簡單測試,發(fā)現(xiàn)確實不會報錯。
現(xiàn)在問題很明確了,但是并沒有得到解決,于是我只能一條條看那難懂的 issues 列表,功夫不負(fù)有心人,我找到了這個帖子 issues 1536,明確的給出了說法,Pythonnet 2.5 does not support .NET 5
、It is supported in v3 previews.
。
好的吧,于是我用 pip list
查看所有 Python 第三方庫的版本
C:\Users\Administrator>pip list
Package Version
---------------- ----------
click 7.1.2
pip 22.0.3
pycparser 2.21
PyQt5 5.15.4
pyqt5-plugins 5.15.4.2.2
PyQt5-Qt5 5.15.2
PyQt5-sip 12.9.1
pyqt5-tools 5.15.4.3.2
python-dotenv 0.19.2
pythonnet 2.5.2
qt5-applications 5.15.2.2.2
qt5-tools 5.15.2.1.2
setuptools 41.2.0
果然,pythonnet 的版本是 2.5.2,我對項目進(jìn)行降級測試,發(fā)現(xiàn) .net core 僅在版本為 net core 1.x 時候支持,2.x-3.x、.NET 5 均不支持。
所以你如果使用的是 pythonnet 2.x 版本,就不要嘗試使用更高版本的 .net core 實現(xiàn)你的功能了,否則需要更新 pythonnet 到更高版本
繼續(xù)看 issues 1536,發(fā)現(xiàn)即使更新了版本還是會存在問題,并跟蹤到了 issues 1473 我嘗試將 pythonnet 升級到 3.x previews 版本但是出現(xiàn)的錯誤,沒有升級成功,所以并沒有繼續(xù)測試后續(xù)的功能。
以上是“Python 3.x踩坑的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。