暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

引用pywin32中constants模块中常量的正确姿势

语和言 2023-02-12
994

一、引言


分享知识+推广我的Python书

此前,本号分享了用pywin32提取Word文件脚注文本的三种方式,文章见


用pywin32提取Word文件脚注文本的三种方式


在这篇文章的讨论环节,笔者提出一个疑问:如何能够让Python认识pywin32扩展库中 constants 模块中的预先定义的常量?比如 wdFootnotesStory
今日便分享引用pywin32中constants模块中预定义常量的正确姿势

环境:64位Win 10中文版 + 64位Python 3.6.5 + 64位Office 2010




二、新书推广

《Python程序设计(基于计算思维和新文科建设)》,ISBN:9787121435577,胡凤国,电子工业出版社,2022年6月。


本书是电子工业出版社在国内较早采用纸质版+电子版的创新图书发行模式的第一次尝试。本书是这套创新图书的纸质版部分,与之内容互补的电子版图书将稍后出版。

本书的内容包含基础篇排错篇两部分:

基础篇介绍Python程序设计的入门知识,共12章,包括:

⑴ Python简介
⑵ Python软件的安装和Python程序运行;
⑶ Python的基本概念(对象、数据类型、表达式、内置函数);
 输入和输出;
⑸ 程序设计的三种基本结构;
⑹ 函数和类;
⑺ 序列操作(列表、元组、集合、字典);
⑻ 字符串;
⑼ 正则表达式;
⑽ 文件读写;
⑾ 目录与文件操作;
⑿ 常用标准库介绍。

排错篇总结初学者常遇到的错误并介绍程序调试方法,包含2章:

⒀ Python错误类型;
⒁ Python代码调试。 

本书详细目录见本文末尾。

与本书内容互补的电子版图书包含文本篇应用篇两部分:

文本篇:介绍字符集、编码和文本文件读写的知识,包含了对国家规范《通用规范汉字表》8105个汉字当中难以输入和难以显示的汉字的处理。

应用篇:介绍Word、Excel、PPT、PDF、图片等常用办公文件的处理,是大家提高办公和科研效率的好帮手。

本书配套有详细的PPT和教学大纲,还有全部例题的程序代码和绝大部分思考题的程序代码。

本书配套PPT里面还加入了配套电子版图书中的部分内容,比如字符集和编码,不同编码的文本文件的读写,Word、Excel、PPT、PDF等一些常用办公文件的读写。

本书的配套资源可以在电子工业出版社官网下载。

本书的读者对象:

1、大学文科生 可选本书当Python教材或自学Python的参考书。

2、大学理工科学生 可选本书当自学Python的参考书。

3、文科领域的教师、科研人员和研究生
可拿本书当工具书,本书的配套程序会为您节省效率,在当前大数据和新文科的背景下,本书可以为相关领域的量化研究提供技术支持。

4、理工科领域的教师、科研人员和研究生

本书配套的电子版图书中的编码和文本处理知识也可以作为理工科教师和科研人员处理文本数据的参考资料之一,毕竟专门开辟章节介绍国家标准《通用规范汉字表》汉字处理的程序设计图书并不多见。


5、青少年学生
本书有专门的海龟画图章节,有大量的有趣数学题目,可以培养学生的计算思维,适合对编程感兴趣的中小学生阅读,也适合打算让娃参加编程辅导班的家长朋友参考。

本书在各大实体书店和网店均有销售。京东、天猫、当当的购买渠道如下(可扫码直达购买页面)。








三、错误的引用方式


之所以错误,是因为Python不知道constants模块中有什么预先定义的常量,怎么让它知道呢?我们还要创建一个Word进程才行。


不过,下面加了创建Word进程的方法也是错误的:


之所以错误,是因为我们创建Word进程的姿势有问题。让我们看看正确的引用方式。



四、正确的引用方式


在上面的IDLE交互式窗口中,有两个导入语句和一个创建Word进程的语句,缺一不可。


注意,为了使用constants模块中预先定义的常量,我们用来创建Word进程使用的是EnsureDispatch,而不是Dispatch,也不是DispatchEx。


下面简单解释一下。



五、解释


一般情况下,我们看到的创建Word进程的代码有三种:


方式一:用 Dispatch


    from win32com.client import Dispatch
    word = Dispatch("Word.Application")


    方式二:用 DispatchEx


      from win32com.client import DispatchEx
      word = DispatchEx("Word.Application")


      方式三:用 EnsureDispatch


        from win32com.client import constants
        from win32com.client.gencache import EnsureDispatch
        word = EnsureDispatch("Word.Application")

        在创建Word进程之后,为了要操作Word文件,我们还要在Word进程中打开Word文件,以便创建一个Word文档对象,然后再使用这个Word文档对象的属性或方法进行操作。


        无论我们使用什么方法创建了Word进程,下一步创建Word文档对象的语句都是一样的:


          doc = word.Documents.Open(fn)   # 这里fn是某个Word文件的全路径名


          如果是用前两种方法创建的Word进程,那么,在Word文档对象创建之后,Python不知道这个Word文档对象有哪些属性和方法可以使用,也不知道pywin32扩展库的constants模块预先定义了哪些常量。这被称为“后期绑定”(late binding)。


          如果是用第三种方法创建的Word进程,那么,在Word文档对象创建之后,Python就能够知道这个Word文档对象有哪些属性和方法可以使用,同时也会知道pywin32扩展库的constants模块预先定义了哪些常量。这被称为早期绑定early binding)。


          在 late binding 模式下,查看常量 constants.wdFootnotesStory 的值时,Python都不认识它,自然会报错。在 early binding 模式下查看常量 constants.wdFootnotesStory 的值时,Python已经认识它了,所以就不会报错。


          据网上的资料说, late binding 模式创建Word进程比较简单, early binding 模式创建Word进程比较复杂,它会引发一些操作,什么操作我们不必深究,反正这些操作会产生一些文件,Python就是通过读取这些文件来知道Word文档对象有哪些属性和方法,同时也会知道constants模块预先定义了哪些常量以及这些常量各自的值。


          这些文件我们可以在类似如下的目录中找到:


          C:\Users\******\AppData\Local\Temp\gen_py\3.6\00020905-0000-0000-C000-000000000046x0x8x5


          这个目录各人电脑上是不一样的,跟用户名有关,跟Python的版本有关,可能还跟其它因素有关。在用early binding 模式创建Word进程之后,我们可以通过运行如下的代码来找到该目录:


            from os.path import dirname
            import sys
            print(dirname(sys.modules[word.__module__].__file__))


            在笔者电脑上,这个目录下有一大堆文件:


            很多文件打开之后我们是看不懂的,不过,有一个文件能够看懂,这就是__init__.py。我们用代码编辑器打开该文件,搜索 wdFootnotesStory 这个字符串,发现在2546行(其它电脑可能不是这个行数)找到了这个预定义常量:



            我们现在知道了,Python之所以认识 constants.wdFootnotesStory ,就是因为它在创建Word进程的时候,读取到了这个文件的内容。Python也就知道了符号常量 constants.wdFootnotesStory 代表的数值是 2。


            在 late binding 模式下,如果读取不到这个文件,Python不会主动生成一些文件再去读取,但是在 early binding 模式下,如果读取不到这个文件,它会首先在目录 


            C:\Users\******\AppData\Local\Temp\gen_py\3.6\00020905-0000-0000-C000-000000000046x0x8x5


            下生成一些文件,然后再去读取,确保能读取到这些文件的内容。

            顺便说一下,有的时候,我们没有用 EnsureDispatch 来创建Word进程,使用了常量 constants.wdFootnotesStory 的程序代码也不会报错,例如:


            这是因为,在此之前我们曾经用  EnsureDispatch 创建过Word进程,已经生成了目录:


            C:\Users\******\AppData\Local\Temp\gen_py\3.6\00020905-0000-0000-C000-000000000046x0x8x5


            在这个目录已经存在的前提下,无论我们使用三种创建Word进程的方式的哪一种,都能让Python认识模块 constants 中的常量。


            如果不确定上述目录是否存在,就只能用  EnsureDispatch 创建Word进程,才能确保Python认识模块 constants 中的常量。


            但是,用  EnsureDispatch 创建Word进程也有一个缺点,那就是当我们电脑上本来就有手动打开的Word文件进行编辑时,电脑上已经有一个Word进程存在, EnsureDispatch 就不会新建Word进程,而是用原本存在的Word进程打开我们Python程序要操作的Word文件,这样,但我们操作完执行 word.Quit() 命令关闭Word进程的时候,会把我们本来正在手工编辑的Word文件强行关掉,如果没有及时保存的话,哭都来不及的。


            用 Dispatch 创建Word进程,也有这样的问题。


            用 DispatchEx 创建Word进程,就完全避开了这样的问题。因为Python会新开一个Word进程,关闭Word进程的时候,只关闭新开的Word进程,对原本正在编辑Word文件的Word进程毫无影响。



            六、总结


            第一、用 Dispatch 和 DispatchEx 创建Word进程,不保证Python认识模块 constants 中的常量;而  EnsureDispatch 创建Word进程,能确保Python认识模块 constants 中的常量。

            本号在文章 《用pywin32提取Word文件脚注文本的三种方式》 中提到的程序,就可以通过引用 constants 中的常量符号让程序代码更清晰易懂(下面代码中红框内部是跟之前不一样的地方):


            第二、当我们用  EnsureDispatch 创建过Word进程之后,只要那个生成的目录还在,我们以后再引用模块 constants 中的常量时,可以直接用 Dispatch 或 DispatchEx 创建Word进程而不报错,但问题是,我们写程序的时候,不确定运行程序的电脑上是不是存在这个目录。所以,为稳妥起见,为确保Python认识 constants 中的常量,还是  EnsureDispatch 创建Word进程比较好一些。


            第三、用 Dispatch 和  EnsureDispatch 创建Word进程时,会优先借用内存中原本存在的Word进程,我们在程序中关闭Word进程时可能会导致数据丢失;但用 DispatchEx 创建Word进程,总会新建Word进程,操作完关闭Word进程不会对内存中原有的Word进程产生任何影响。


                可见,使用独立Word进程与确保Python认识模块 constants 中的常量是一对矛盾。



            七、讨论


            既然使用独立Word进程与确保Python认识模块 constants 中的常量是一对矛盾,那么,当我们既要又要的时候,我们该怎么处理呢?

            这个问题,先留给同学们和其他读者朋友思考。本号后面有时间的话会给出解决方案。



            八、联系交流


            由于本号文章以辅助教学为主,笔者不建议自己的学生直接拿代码运行,而是建议在理解了思路之后自己敲代码来加深印象,所以本号一般不直接贴代码。如果其他读者朋友有需要代码,请关注本号,加笔者微信联系。

            欢迎关注微信公众号“语和言”,本公众号将不定期发布对图书《Python程序设计(基于计算思维和新文科建设)》中的Python知识点进行解读和补充的内容。语和言公众号还有读者交流群,读者朋友可以入群一起讨论问题。


            欢迎跟图书《Python程序设计(基于计算思维和新文科建设)》的作者胡凤国老师进行交流,电邮:cuchufengguo@163.com



            九、图书目录


            图书《Python程序设计(基于计算思维和新文科建设)》目录如下(手机端可以用手指上下滑动下面灰色区域的文字来查看全部目录,电脑端可以用鼠标滚动滚轮或拖动下面文本框右边的滚动条来浏览全部目录):


            第一篇 基础篇


            第1章 Python介绍
            1.1 什么是Python
            1.1.1 有一种编程语言叫Python
            1.1.2 Python的发展史
            1.1.3 Python的版本选择
            1.2 为什么要学习Python
            1.2.1 为什么要学编程
            1.2.2 学编程为什么选Python
            1.3 怎样学习Python

            第2章 Python的安装和运行
            2.1 安装Python软件
            2.1.1 软件下载
            2.1.2 安装
            2.1.3 测试
            2.2 运行Python代码
            2.2.1 交互式运行
            2.2.2 脚本式运行
            2.2.3 命令行运行
            2.2.4 扩展式运行
            2.2.5 运行Python代码的误区
            2.2.6 合法的Python语句
            2.3 Python代码书写规范
            2.4 Python扩展库和标准库
            2.4.1 扩展库的安装
            2.4.2 标准库和扩展库的使用

            第3章 Python的基本概念
            3.1 数据和数据类型
            3.1.1 数据与对象
            3.1.2 数据类型
            3.2 变量与关键字
            3.2.1 对象的存储
            3.2.2 变量
            3.2.3 关键字
            3.3 运算符和表达式
            3.3.1 常量数据和变量数据
            3.3.2 运算符
            3.3.3 表达式
            3.4 内置函数和内置对象
            3.4.1 内置函数
            3.4.2 内置对象
            思考题

            第4章 输入和输出
            4.1 数据输入
            4.1.1 获取输入数据
            4.1.2 转换输入数据
            4.1.3 处理输入错误
            4.2 数据输出
            4.2.1 *简单的数据输出
            4.2.2 数据格式化
            4.3 综合举例
            4.3.1 十进制转二进制(一)
            4.3.2 鸡兔同笼(一)
            4.3.3 韩信点兵(一)
            4.3.4 换酒问题(一)
            4.3.5 最大公约数(一)
            4.3.6 交换两个变量的值
            思考题

            第5章 基本程序结构
            5.1 结构化程序设计
            5.1.1 顺序结构
            5.1.2 选择结构
            5.1.3 循环结构
            5.1.4 结构嵌套
            5.2 顺序结构
            5.2.1 顺序结构举例
            5.2.2 顺序结构的拼接
            5.3 选择结构
            5.3.1 单分支选择结构
            5.3.2 双分支选择结构
            5.3.3 多分支选择结构
            5.3.4 选择结构的嵌套
            5.3.5 条件表达式
            5.3.6 选择结构的多样性
            5.4 循环结构
            5.4.1 while循环
            5.4.2 for 循环
            5.4.3 continue语句
            5.4.4 break语句
            5.4.5 循环结构中的else子句
            5.5 循环结构的嵌套
            5.6 综合举例
            5.6.1 十进制转二进制(二)
            5.6.2 鸡兔同笼(二)
            5.6.3 韩信点兵(二)
            5.6.4 换酒问题(二)
            5.6.5 *大公约数(二)
            5.6.6 百钱百鸡
            5.6.7 兔子数列
            5.6.8 奇数幻方
            5.6.9 哥德巴赫猜想(一)
            5.6.10 信息加密(一)
            5.6.11 求圆周率
            5.6.12 海龟画图
            思考题

            第6章 函数和类
            6.1 使用函数的好处
            6.2 函数的定义和调用
            6.2.1 函数的定义
            6.2.2 函数的调用
            6.2.3 关于函数返回值的注意事项
            6.3 函数参数的传递与接收
            6.3.1 函数参数的传递方式
            6.3.2 函数形参接收实参的形式
            6.4 函数中的局部变量和全局变量
            6.5 lambda表达式
            6.6 生成器函数
            6.7 自定义函数库
            6.8 递归函数
            6.8.1 什么是递归函数
            6.8.2 递归函数和算法
            6.8.3 Python中的*大递归次数
            6.8.4 递归函数举例
            6.8.5 递归与循环的关系
            6.8.6 递归函数的时间效率
            6.9 类和对象
            6.9.1 类和对象的概念
            6.9.2 类的定义和使用示例
            思考题

            第7章 Python的序列操作
            7.1 序列结构
            7.2 列表及其操作
            7.2.1 列表的标准形式
            7.2.2 列表对象的创建和删除
            7.2.3 列表元素的读取、修改和删除
            7.2.4 列表对象常用的方法
            7.2.5 用内置函数对列表进行操作
            7.2.6 用运算符对列表进行运算
            7.2.7 列表推导式
            7.3 元组及其操作
            7.3.1 元组的概念
            7.3.2 元组的标准形式
            7.3.3 元组对象的创建
            7.3.4 元组元素的读取
            7.3.5 元组对象常用的方法
            7.3.6 用内置函数对元组进行操作
            7.3.7 用运算符对元组进行运算
            7.3.8 生成器推导式
            7.4 字典及其操作
            7.4.1 字典的标准形式
            7.4.2 字典的创建
            7.4.3 字典元素的添加和修改
            7.4.4 字典元素的读取
            7.4.5 字典元素的删除
            7.4.6 字典对象常用的方法
            7.4.7 用内置函数对字典进行操作
            7.4.8 用运算符对字典进行运算
            7.5 集合及其操作
            7.5.1 集合的标准形式
            7.5.2 集合的创建
            7.5.3 集合元素的添加
            7.5.4 集合元素的删除
            7.5.5 集合元素的读取
            7.5.6 集合对象常用的方法
            7.5.7 用内置函数对集合进行操作
            7.5.8 用运算符对集合进行运算
            7.6 切片
            7.6.1 切片的格式
            7.6.2 用切片对列表的元素进行增删改
            7.7 NumPy和Pandas扩展库的简单操作
            7.7.1 NumPy扩展库
            7.7.2 Pandas扩展库
            7.8 序列类对象的通用操作总结
            7.9 综合举例
            7.9.1 判断列表中有无重复元素
            7.9.2 百分制转五分制
            7.9.3 中文星期名称转英文星期名称
            7.9.4 判断某年某月有几天
            7.9.5 求两个可迭代对象的笛卡尔积
            7.9.6 查找列表中*小元素的所有位置
            7.9.7 查找N以内的所有素数
            7.9.8 年份生肖(一)
            7.9.9 农村小孩的乳名(一)
            7.9.10 天干地支顺序配对(一)
            7.9.11 判断黑洞数(一)
            7.9.12 哥德巴赫猜想(二)
            7.9.13 信息加密(二)
            思考题

            第8章 字符串
            8.1 字符串的表示
            8.1.1 字符串界定符
            8.1.2 转义字符
            8.1.3 原始字符串
            8.1.4 字符串和字符的区分
            8.1.5 字符串的标准形式
            8.1.6 长字符串的表示方法
            8.1.7 三引号注释
            8.2 字符串的操作
            8.2.1 Python关于对象的通用操作
            8.2.2 关于序列类对象的通用操作
            8.2.3 关于有序序列类对象的通用操作
            8.2.4 关于元素可比较的有序序列类对象的通用操作
            8.2.5 针对字符串对象的其他操作
            8.3 字符串方法
            8.3.1 格式化类的方法
            8.3.2 排版类的方法
            8.3.3 类型判断类的方法
            8.3.4 查找类的方法
            8.3.5 统计类的方法
            8.3.6 首尾匹配类的方法
            8.3.7 分割类的方法
            8.3.8 合并类的方法
            8.3.9 大小写转换类的方法
            8.3.10 削边类的方法
            8.3.11 替换类的方法
            8.3.12 编码解码类方法
            8.4 字词统计和中文分词
            8.4.1 字符统计
            8.4.2 词语统计
            8.4.3 中文自动分词和词性标注
            8.5 综合举例
            8.5.1 屏蔽敏感词
            8.5.2 年份生肖(二)
            8.5.3 农村小孩的乳名(二)
            8.5.4 天干地支顺序配对(二)
            8.5.5 判断黑洞数(二)
            8.5.6 哥德巴赫猜想(三)
            8.5.7 信息加密(三)
            8.5.8 公民身份号码
            8.5.9 十进制转任意进制
            思考题

            第9章 正则表达式
            9.1 什么是正则表达式
            9.2 正则表达式的语法
            9.2.1 万能符
            9.2.2 转义符
            9.2.3 元字符
            9.2.4 选字符
            9.2.5 连字符
            9.2.6 脱字符
            9.2.7 简写符
            9.2.8 选串符
            9.2.9 定位符
            9.2.10 分组符
            9.2.11 数量符
            9.2.12 非贪婪匹配标识符
            9.2.13 子表达式
            9.2.14 预查
            9.2.15 命名子表达式
            9.3 在Python中使用正则表达式
            9.3.1 re.findall函数
            9.3.2 re.match函数
            9.3.3 re.search函数
            9.3.4 re.split函数
            9.3.5 re.sub和re.subn函数
            9.3.6 re.escape函数
            9.3.7 re.compile函数
            9.4 综合举例
            思考题

            第10章 文件读写
            10.1 文件简介
            10.2 内置函数open
            10.2.1 open函数的参数介绍
            10.2.2 open函数的mode参数详解
            10.2.3 文件对象的方法
            10.3 文本文件的读写
            10.3.1 从文本文件读取数据
            10.3.2 将数据写入文本文件
            10.3.3 用上下文管理语句with来管理文本文件读写
            10.4 JSON文件的读写
            10.5 CSV文件的读写
            10.6 二进制文件的读写
            思考题

            第11章 目录与文件操作
            11.1 文件和目录
            11.1.1 驱动器
            11.1.2 目录、文件夹、路径
            11.1.3 目录名和文件名的命名规范
            11.1.4 当前目录
            11.1.5 环境变量
            11.1.6 绝对路径和相对路径
            11.1.7 可执行程序和应用程序
            11.1.8 默认应用程序
            11.2 文件目录操作的有关标准库介绍
            11.2.1 os.path标准库介绍
            11.2.2 os标准库介绍
            11.2.3 shutil标准库的常用函数介绍
            11.3 文件目录操作需要考虑的因素
            11.4 文件目录操作
            11.4.1 无读取写入文件
            11.4.2 读取文件无写入
            11.4.3 无读取写入目录
            11.4.4 读取目录无写入
            11.4.5 读取文件写入文件
            11.4.6 读取文件写入目录
            11.4.7 读取目录写入文件
            11.4.8 读取目录写入目录
            思考题

            第12章 常用的Python标准库
            12.1 collections标准库
            12.2 copy标准库
            12.3 decimal标准库
            12.4 fractions标准库
            12.5 functools标准库
            12.6 itertools标准库
            12.6.1 combinations对象
            12.6.2 permutations对象
            12.6.3 product对象
            12.7 math标准库
            12.8 random标准库
            12.8.1 choice函数
            12.8.2 randint函数
            12.8.3 random函数
            12.8.4 randrange函数
            12.8.5 sample函数
            12.8.6 shuffle函数
            12.8.7 uniform函数
            12.8.8 应用示例
            12.9 sys标准库
            12.9.1 获取Python解释器的位置
            12.9.2 添加扩展库搜索目录
            12.9.3 终止运行Python程序
            12.9.4 获取命令行参数
            12.10 tempfile标准库
            12.10.1 功能介绍
            12.10.2 应用示例
            12.11 time标准库
            12.11.1 有关概念
            12.11.2 函数介绍
            12.11.3 应用示例
            12.12 datetime标准库
            12.12.1 datetime标准库定义的常用类
            12.12.2 应用示例
            思考题

            第二篇 排错篇

            第13章 常见错误类型
            13.1 编码错误
            13.2 缩进错误
            13.2.1 不当缩进错误
            13.2.2 混用制表符和空格
            13.3 语法错误
            13.3.1 混淆大小写
            13.3.2 混淆全半角
            13.3.3 写错关键词
            13.3.4 括号不配对
            13.3.5 用三引号注释代码块引起语法错误
            13.3.6 其他语法错误
            13.4 运行错误
            13.4.1 数学运算错误
            13.4.2 数据类型错误
            13.4.3 下标越界错误
            13.4.4 文本文件编码错误
            13.4.5 扩展库出错
            13.4.6 计算机配置环境出错
            13.5 逻辑错误
            13.5.1 循环终值设定有问题
            13.5.2 不同用途的变量同名
            13.5.3 不该变的变量值被改变
            13.5.4 语句缩进层次不清
            13.5.5 混淆运算符的优先级
            13.5.6 列表赋值错误
            13.5.7 调用对象的方法不加括号
            13.5.8 算法错误

            第14章 代码调试
            14.1 输出对比法
            14.2 IDLE调试法
            14.3 装饰器方法

            附录
            附录A 环境变量设置
            附录B 常用Python语句
            附录C 常用Python运算符
            附录D 内置函数format
            附录E %格式化方法
            附录F 不能显示的四字节汉字
            附录G PyPDF2的BUG及解决方案

            参考文献


            文章转载自语和言,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论