Python,踩坑实战总结_数据库
因项目需要最近接手维护后续Python程序并做后续开发,下面这篇文章主要给大家介绍了关于Python?3.x踩坑的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
纪要
本文用来记录学习Python过程中遇到的一些小问题。遇到重大问题会单独开页分析学习。
处处有坑
1. 文件读取 open# 我们打开文件使用 open 方法xml = open("demo.xml")# 使用 open 命令读取文件时,经常会出现下列错误Traceback (most recent call last): File "TempConvert.py", line 84, in lt;modulegt; for line in xml:UnicodeDecodeError: 'gbk' codec can't decode byte 0x8d in position 38: illegal multibyte sequence# 出现这个错误的原因是系统默认打开的编码方式和文件不一致,需要通过带格式参数的方式打开# 比如,文件如果是 utf-8 格式文件,则需要采用下列格式参数:xml = open("demo.xml", encoding="utf-8")
2. 正则表达式 S 与 S
首先提出一个问题,用正则表达式获取字符串中的邮箱列表。例如:csev@umich.edu给cwen@iupui.edu发了一条关于下午两点见面的信息
# 我们可以通过一个简单的正则表达式,这里不考虑其他复杂条件import restr = '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']# 然而我们发现,下列正则表达式也有同样的结果lst2 = re.findall('S+@S+', s)print(lst2)
这很奇怪,因为在其他语言的正则表达式中,S和S代表不同的含义,S代表一个非空字符,S代表匹配的字符串S,所以我们尝试如下:
'S' == 'S' # Truelen('S') # 2len('S') # 2
你惊呆了吗?所以我又试了一次。
's' == 's' # Truelen('s') # 2len('s') # 2'n' == 'n' # Falselen('n') # 2len('n') # 1
我们发现s和n的情况并不相同。经过一番查询,我们找到了下面这篇文章:
Python正则表达式# 39; s # 39vs # 39 s # 39
文中提到
唐# 39;不要混淆python级别的字符串转义和regex级别的字符串转义。因为s不是python级别的可转义字符,所以解释器将像 s这样的字符串理解为两个字符和s。用n替换s,并将其理解为换行符。
不要混淆Python中的字符串转义和正则表达式级别的字符串转义。因为s在Python中不是可转义字符,所以解释器将像s这样的字符串理解为两个字符和s。用n替换s,n将其解释为换行符。
虽然没有更权威的说法,但也反映出如果是s,就当两个字;如果是s,则视为一个字符,因为 是转义字符,s也被视为s两个字符。所以才会出现这种情况。
's' == 's' # True
3. 正则表达式匹配方法 match
在学习正则表达式匹配规则的时候,我发现Python的正则匹配方法和其他的略有不同,比如上一篇文章提到的S和S问题,然后是下面的:
Python的正则匹配是从零开始的。例如,如果我们想在字符串中匹配一个电话号码。
您可以在JS中使用以下常规匹配
// 使用 JS 的方式,我们可以有下列的写法'我的手机号码是15900000000不要告诉别人,否则我就把你号码是13900000000告诉别人'.match(/1[0-9]{10}/g)// (2) ['15900000000', '13900000000']
但是如果你把同样的规则放在Python里,就没那么好用了。
import restr = '我的手机号码是15900000000不要告诉别人,否则我就把你号码是13900000000告诉别人'# 错误的写法mah = re.match('1[0-9]{10}', str)print(mah)# None
因为Python的match默认从头匹配,而1不一定是给定字符串的第一个字母。
# 应该使用另一个方法 findall 代替mah = re.findall('1[0-9]{10}', str)print(mah)# ['15900000000', '13900000000']
从这一点上,我们可以看到Python的很多库都提供了不同于其他语言的方法。作为其他语言转Python的小伙伴,应该实际测试一下方法,或者在熟悉的情况下使用。而不是不加思考的用固定的方式思考,你觉得Python就跟其他语言一样。
4. 帮助文档 pydoc
可以通过以下方式查看Python中库或方法的帮助:
【可选】在命令行环境下输入 python 即可进入 Python 编译环境使用 dir(库、对象) 的方式查看库或者对象可以提供的方法dir('字符串') # 查看字符串有哪些操作方法import redir(re) # 查看正则表达式库有哪些操作方法使用 help(库、对象) 的方式查看库或者对象的帮助信息import rehelp(re) # 查看正则表达式库的帮助文档dir(re.match) # 查看正则表达式的 `match` 的帮助信息
如果我们想将帮助文档写入文本文件,我们可以在命令行中使用命令:
# 将 re 库的帮助信息到 html 文档python -m pydoc -w re# windows 下可以用下列方法输出到文本文件python -m pydoc re gt; d:re.txt
关于pydoc的更多信息,请参考官方文档pydoc。
5. 字符串 encode base64 编码
在某些教程中,字符串的base64编码如下:
str = "this is string example....wow!!!";print "Encoded String: " + str.encode('base64','strict')# 预计输出结果Encoded String: dGhpcyBpcyBzdHJpbmcgZXhhbXBsZS4uLi53b3chISE=
但是这段代码会报告一个错误:
LookupError:# 39;base64 # 39不是文本编码;使用codecs.encode()处理任意编解码器
据了解,这个错误的写法其实来自于Python 2.x的写法,但是在Python 3.x中写法发生了变化,字符串正确的base64编码方式应该是:
import base64str = "this is string example....wow!!!"# 返回原字符串编码为字节串对象的版本strb = str.encode()base64b = base64.b64encode(strb)base64 = base64b.decode()print(base64)
6. Python 调用 C# 动态链接库
百度搜了很多关于Python调用C#动态链接库的方法,大部分是以下代码:
import clr# clr.FindAssembly('DotNetWithPython.dll') # dll在当前目录clr.AddReferenceToFile('DotNetWithPython.dll') # dll在当前目录from DotNetWithPython import * # 导入动态链接库中的所有类if __name__ == '__main__': mainapp = MainForm() # 初始化 MainForm 类对象
不幸的是,没有任何东西能正常工作,我也不知道到底哪里出了问题,为什么不能工作。这些都是Python 2.x的用法吗?(我学的是Python 3.x)
做了如下思考:
Python clr是PythonNet,那你是直接去PythonNet官方还是github找相关代码?
于是我找到了下面的地址:pythonnet.github.io/按照里面给的代码一个一个的试,首先是这个:
from System import Stringfrom System.Collections import *
当我们发现以下情况时,我们将报告错误:
Traceback(最近一次调用last):
File quot;d:/Temp/python projects/Demos/dlldo . py quot;,第10行,在lt;modulegt
来自系统导入字符串
ModuleNotFoundError:没有名为#39的模块;系统# 39;
我们尝试将代码修改为:
import clrfrom System import Stringfrom System.Collections import *
可以肯定的是,我们对。NET相关的类必须导入clr。我们继续尝试,当我们尝试下面的代码时:
import clrfrom System.Drawing import Pointp = Point(5, 5)
又错了:
d:/Temp/python projects/Demos/dlldo . py:11:deprecation warning:找到了该模块,但不在引用的命名空间中。
不推荐使用隐式加载。请使用clr。add reference(# 39;系统。39号图纸;).
来自系统。绘图导入点
从给出的错误消息中,我们可以看到我们需要在空之间引用:
import clrclr.AddReference('System.Drawing')from System.Drawing import Pointp = Point(5, 5)print(p)# {X=5,Y=5}
至此,我们基本确定Python调用C#没有问题,那么如果我们可以调用自己定义的dll动态链接库呢?我们尝试按如下方式引用系统类:
import clrclr.AddReference('DotNetWithPython')from DotNetWithPython import MainFormmainapp = MainForm()
结果中的错误:
Traceback(最近一次调用last):
File quot;d:/Temp/python projects/Demos/dlldo . py quot;,第12行,在lt;modulegt
from DotNetWithPython import MainForm
ModuleNotFoundError:没有名为# 39;DotNetWithPython # 39
所以我想:
Clr通常可以调用。NET本身,但是我不能调用自己的动态链接库。CLR和。NET本身就是不在系统环境中,它的dll在当前目录或者其他目录中。
所以我们使用dir(clr)来确定是否有可用的方法。
import clrdir(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']
我们发现FindAssembly这个方法感觉很像,就按照之前system类的引用方法和这句话测试了一下:
import clrclr.FindAssembly('DotNetWithPython.dll')clr.AddReference('DotNetWithPython')from DotNetWithPython import MainFormmainapp = MainForm()
还是同一个错误,我都要哭了,只能在几期PythonNet Github里找答案了。我发现很多人提出这个问题,问题就被锁定了。net core和net 5,但这种问题在。Net框架。所以我建立了一个基于。Net Framework 4.x进行简单测试,发现没有报错。
现在问题清楚了,但还没解决,只能一个一个看难题清单,一切都有回报。我找到这个帖子,问题1536,给了一个明确的说法,Python NET 2.5不支持。NET 5,v3预览版支持。
好了,所以我用pip list检查所有Python第三方库的版本。
c: Users administrator gt;pip列表
包版本
-
点击7 . 1 . 2
pip 22 . 0 . 3
pyc parser 2.21
pyqt 5 5 . 15 . 4
pyqt 5-插件5 . 15 . 4 . 2 . 2
pyqt 5-Qt 5 . 15 . 2
pyqt 5-sip 12 . 9 . 1
pyqt 5
果然,pythonnet的版本是2.5.2。我降低了这个项目的等级,发现。只有在版本为net core 1.x时才支持net core,2.x-3.x和不支持。净5。
所以如果你用的是python net 2 . x版,不要试图用更高版本的。net核心来实现你的功能,或者你需要更新Python NET到更高的版本。
继续看1536期,发现即使更新了版本,还是会有问题,追溯到1473期。我尝试将pythonnet升级到3.x版本预览版,但是出现了错误,升级不成功,所以没有继续测试后续功能。
总结
关于Python3.x踩坑的实战总结这篇文章到此为止。关于Python 3.x踩坑的更多信息