網(wǎng)站首頁 編程語言 正文
紀(jì)要
本文用于記錄學(xué)習(xí) Python 過程中遇到的一些小問題,如果遇到的是比較大的問題會(huì)單獨(dú)開頁面分析學(xué)習(xí)
處處有坑
1. 文件讀取 open
# 我們打開文件使用 open 方法 xml = open("demo.xml") # 使用 open 命令讀取文件時(shí),經(jīng)常會(huì)出現(xiàn)下列錯(cuò)誤 Traceback (most recent call last): File "TempConvert.py", line 84, infor line in xml: UnicodeDecodeError: 'gbk' codec can't decode byte 0x8d in position 38: illegal multibyte sequence
# 出現(xiàn)這個(gè)錯(cuò)誤的原因是系統(tǒng)默認(rèn)打開的編碼方式和文件不一致,需要通過帶格式參數(shù)的方式打開 # 比如,文件如果是 utf-8 格式文件,則需要采用下列格式參數(shù): xml = open("demo.xml", encoding="utf-8")
2. 正則表達(dá)式 \S 與 \\S
首先提出一個(gè)問題,使用正則表達(dá)式獲取到字符串中的郵箱列表。 例:A message from csev@umich.edu to cwen@iupui.edu about meeting @2PM
# 我們可以通過一個(gè)簡(jiǎn)單的正則表達(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)
這就比較奇怪了,因?yàn)樵谄渌Z言的正則表達(dá)式中,\S
和 \\S
代表的含義并不相同,\S
表示一個(gè)非空字符,而 \\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á)式級(jí)別的字符串轉(zhuǎn)義。由于 s 在 Python 不是可轉(zhuǎn)義字符,解釋器將 \s 這樣的字符串理解為兩個(gè)字符 \ 和 s。將 s 替換為 n,它將其理解為換行符。
雖然沒有提及到更權(quán)威的說法,但是也反應(yīng)出了,如果是 \s
會(huì)被當(dāng)做是兩個(gè)字符,如果是 \\s
因?yàn)?\\
是可轉(zhuǎn)義字符,被當(dāng)做了 \
一個(gè)字符,\\s
也就被當(dāng)做了 \s
兩個(gè)字符。所以才會(huì)出現(xiàn)這種情況。
'\s' == '\\s' # True
3. 正則表達(dá)式匹配方法 match
在學(xué)習(xí)正則表達(dá)式匹配規(guī)則時(shí)候發(fā)現(xiàn),Python 正則匹配的方式和其他的稍有不同,比如上一條提到的 \S
與 \\S
的問題,然后還有下面的:
Python 的正則匹配是從頭匹配,舉個(gè)例子,如果我們要匹配一個(gè)字符串中的電話號(hào)碼
在 JS 中你可以用下列的正則匹配
// 使用 JS 的方式,我們可以有下列的寫法 '我的手機(jī)號(hào)碼是15900000000不要告訴別人,否則我就把你號(hào)碼是13900000000告訴別人'.match(/1[0-9]{10}/g) // (2) ['15900000000', '13900000000']
但是如果你把同樣的正則放到 Python 中則不那么好使
import re str = '我的手機(jī)號(hào)碼是15900000000不要告訴別人,否則我就把你號(hào)碼是13900000000告訴別人' # 錯(cuò)誤的寫法 mah = re.match('1[0-9]{10}', str) print(mah) # None
因?yàn)?Python 的匹配 match
默認(rèn)是從開頭開始匹配的,而 1 并不一定是給定的字符串的首字母。
# 應(yīng)該使用另一個(gè)方法 findall 代替 mah = re.findall('1[0-9]{10}', str) print(mah) # ['15900000000', '13900000000']
從這一點(diǎn)可以看出,Python 的很多庫都提供用不同于其他語言的方法,作為其他語言轉(zhuǎn)學(xué) Python 的小伙伴要實(shí)際測(cè)試過方法或者熟知的情況下使用,而不應(yīng)該不加思考的定式思維,一廂情愿的覺得 Python 就和其他的語言一樣。
4. 幫助文檔 pydoc
Python 中對(duì)庫或者方法的幫助查看可以用下列的方式進(jìn)行:
- 【可選】在命令行環(huán)境下輸入 python 即可進(jìn)入 Python 編譯環(huán)境
- 使用
dir(庫、對(duì)象)
的方式查看庫或者對(duì)象可以提供的方法
dir('字符串') # 查看字符串有哪些操作方法 import re dir(re) # 查看正則表達(dá)式庫有哪些操作方法
- 使用
help(庫、對(duì)象)
的方式查看庫或者對(duì)象的幫助信息
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
5. 字符串 encode base64 編碼
一些教程上對(duì)字符串的 base64 編碼的方式是這樣的:
str = "this is string example....wow!!!"; print "Encoded String: " + str.encode('base64','strict') # 預(yù)計(jì)輸出結(jié)果 Encoded String: dGhpcyBpcyBzdHJpbmcgZXhhbXBsZS4uLi53b3chISE=
但是這個(gè)代碼卻會(huì)報(bào)錯(cuò):
LookupError: 'base64' is not a text encoding; use codecs.encode() to handle arbitrary codecs
據(jù)了解,這種錯(cuò)誤的寫法其實(shí)是來源于 Python 2.x 的寫法,但是在 Python 3.x 中寫法發(fā)生了變化,字符串的 base64 正確編碼方式應(yīng)該是:
import base64 str = "this is string example....wow!!!" # 返回原字符串編碼為字節(jié)串對(duì)象的版本 strb = str.encode() base64b = base64.b64encode(strb) base64 = base64b.decode() print(base64)
6. Python 調(diào)用 C# 動(dòng)態(tài)鏈接庫
在百度搜索了很多關(guān)于 Python 調(diào)用 C# 動(dòng)態(tài)鏈接庫的方式,大多是如下代碼:
import clr # clr.FindAssembly('DotNetWithPython.dll') # dll在當(dāng)前目錄 clr.AddReferenceToFile('DotNetWithPython.dll') # dll在當(dāng)前目錄 from DotNetWithPython import * # 導(dǎo)入動(dòng)態(tài)鏈接庫中的所有類 if __name__ == '__main__': mainapp = MainForm() # 初始化 MainForm 類對(duì)象
可惜啊,沒有能正常使用的,我也不清楚到底是哪里出了問題,為什么都沒有效果呢,難不成這些都是 Python 2.x 的用法嗎?(我學(xué)的是 Python 3.x)
作了如下思考:
python 的 clr 即 PythonNet,那么是否直接到 PythonNet 官方或者 github 上查找相關(guān)代碼呢?
于是搜索到了下列地址:pythonnet.github.io/按照里面給出的代碼逐個(gè)嘗試,首先是這個(gè):
from System import String from System.Collections import *
我們發(fā)現(xiàn)會(huì)報(bào)錯(cuò):
Traceback (most recent call last):
? File "d:/Temp/PythonProjects/Demos/DllDo.py", line 10, in
? ? from System import String
ModuleNotFoundError: No module named 'System'
我們嘗試把代碼修改為:
import clr from System import String from System.Collections import *
可以確定,我們對(duì) .NET 相關(guān)類的調(diào)用必須要 import clr
我們繼續(xù)嘗試,當(dāng)嘗試到下列代碼時(shí):
import clr from System.Drawing import Point p = Point(5, 5)
又報(bào)錯(cuò)了:
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
從給出的錯(cuò)誤信息中,我們可以看出,我們需要對(duì)空間進(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 動(dòng)態(tài)鏈接庫呢?我們嘗試按照前文系統(tǒng)類的引用方式:
import clr clr.AddReference('DotNetWithPython') from DotNetWithPython import MainForm mainapp = MainForm()
結(jié)果報(bào)錯(cuò):
Traceback (most recent call last):
? File "d:/Temp/PythonProjects/Demos/DllDo.py", line 12, in
? ? from DotNetWithPython import MainForm
ModuleNotFoundError: No module named 'DotNetWithPython'
于是我又想:
clr 可以正常調(diào)用 .NET 本身提供的類對(duì)象,調(diào)用不到我的 自己寫的動(dòng)態(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)行測(cè)試:
import clr clr.FindAssembly('DotNetWithPython.dll') clr.AddReference('DotNetWithPython') from DotNetWithPython import MainForm mainapp = MainForm()
還是一樣的錯(cuò)誤,我都要哭了,于是我只能到 PythonNet Github 的 issues 中尋找答案,發(fā)現(xiàn)提出這個(gè)問題的人很多,并且問題被鎖定在了 .net core、.net 5,而 .Net Framework 中沒有出現(xiàn)這種問題,我于是新建了一個(gè)基于 .Net Framework 4.x 的項(xiàng)目進(jìn)行簡(jiǎn)單測(cè)試,發(fā)現(xiàn)確實(shí)不會(huì)報(bào)錯(cuò)。
現(xiàn)在問題很明確了,但是并沒有得到解決,于是我只能一條條看那難懂的 issues 列表,功夫不負(fù)有心人,我找到了這個(gè)帖子 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,我對(duì)項(xiàng)目進(jìn)行降級(jí)測(cè)試,發(fā)現(xiàn) .net core 僅在版本為 net core 1.x 時(shí)候支持,2.x-3.x、.NET 5 均不支持。
所以你如果使用的是 pythonnet 2.x 版本,就不要嘗試使用更高版本的 .net core 實(shí)現(xiàn)你的功能了,否則需要更新 pythonnet 到更高版本
繼續(xù)看 issues 1536,發(fā)現(xiàn)即使更新了版本還是會(huì)存在問題,并跟蹤到了 issues 1473 我嘗試將 pythonnet 升級(jí)到 3.x previews 版本但是出現(xiàn)的錯(cuò)誤,沒有升級(jí)成功,所以并沒有繼續(xù)測(cè)試后續(xù)的功能。
總結(jié)
原文鏈接:https://juejin.cn/post/7072639020416630792
相關(guān)推薦
- 2024-03-25 解決idea配置自定義的maven失敗的問題
- 2023-10-09 mobx中react的觀察者
- 2022-07-10 網(wǎng)絡(luò)I/o編程模型23 netty的出站與入站中handler加載與執(zhí)行順序
- 2023-01-05 Kotlin協(xié)程Channel特點(diǎn)及使用細(xì)節(jié)詳解_Android
- 2022-11-16 從Context到go設(shè)計(jì)理念輕松上手教程_Golang
- 2022-10-05 Iptables防火墻tcp-flags模塊擴(kuò)展匹配規(guī)則詳解_安全相關(guān)
- 2022-09-06 C語言常見排序算法之交換排序(冒泡排序,快速排序)_C 語言
- 2022-08-03 基于PyQt5完成pdf轉(zhuǎn)word功能_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支