文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python 3.x踩坑的示例分析

2023-06-29 14:25

关注

这篇文章主要为大家展示了“Python 3.x踩坑的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python 3.x踩坑的示例分析”这篇文章吧。

处处有坑

1. 文件读取 open

# 我们打开文件使用 open 方法xml = open("demo.xml")# 使用 open 命令读取文件时,经常会出现下列错误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
# 出现这个错误的原因是系统默认打开的编码方式和文件不一致,需要通过带格式参数的方式打开# 比如,文件如果是 utf-8 格式文件,则需要采用下列格式参数:xml = open("demo.xml", encoding="utf-8")

2. 正则表达式 \S 与 \\S

首先提出一个问题,使用正则表达式获取到字符串中的邮箱列表。 例:A message from csev@umich.edu to cwen@iupui.edu about meeting @2PM

# 我们可以通过一个简单的正则表达式,这里不考虑其他复杂条件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 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 中的字符串转义和正则表达式级别的字符串转义。由于 s 在 Python 不是可转义字符,解释器将 \s 这样的字符串理解为两个字符 \ 和 s。将 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 中对库或者方法的帮助查看可以用下列的方式进行:

dir('字符串') # 查看字符串有哪些操作方法import redir(re) # 查看正则表达式库有哪些操作方法
import rehelp(re) # 查看正则表达式库的帮助文档dir(re.match) # 查看正则表达式的 `match` 的帮助信息

如果我们是想把帮助文档写入文本文件中,可以在 命令行中 使用命令:

# 将 re 库的帮助信息到 html 文档python -m pydoc -w re# windows 下可以用下列方法输出到文本文件python -m pydoc re > 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: 'base64' is not a text encoding; use codecs.encode() to handle arbitrary codecs

据了解,这种错误的写法其实是来源于 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 (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 clrfrom System import Stringfrom System.Collections import *

可以确定,我们对 .NET 相关类的调用必须要 import clr 我们继续尝试,当尝试到下列代码时:

import clrfrom System.Drawing import Pointp = 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

从给出的错误信息中,我们可以看出,我们需要对空间进行引用:

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 (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 可以正常调用 .NET 本身提供的类对象,调用不到我的 自己写的动态链接库和 .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 感觉很像,于是我们按照前文系统类的引用方式及这一句进行测试:

import clrclr.FindAssembly('DotNetWithPython.dll')clr.AddReference('DotNetWithPython')from DotNetWithPython import MainFormmainapp = MainForm()

还是一样的错误,我都要哭了,于是我只能到 PythonNet Github 的 issues 中寻找答案,发现提出这个问题的人很多,并且问题被锁定在了 .net core、.net 5,而 .Net Framework 中没有出现这种问题,我于是新建了一个基于 .Net Framework 4.x 的项目进行简单测试,发现确实不会报错。

现在问题很明确了,但是并没有得到解决,于是我只能一条条看那难懂的 issues 列表,功夫不负有心人,我找到了这个帖子 issues 1536,明确的给出了说法,Pythonnet 2.5 does not support .NET 5It 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,我对项目进行降级测试,发现 .net core 仅在版本为 net core 1.x 时候支持,2.x-3.x、.NET 5 均不支持。

所以你如果使用的是 pythonnet 2.x 版本,就不要尝试使用更高版本的 .net core 实现你的功能了,否则需要更新 pythonnet 到更高版本

继续看 issues 1536,发现即使更新了版本还是会存在问题,并跟踪到了 issues 1473 我尝试将 pythonnet 升级到 3.x previews 版本但是出现的错误,没有升级成功,所以并没有继续测试后续的功能。

以上是“Python 3.x踩坑的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯