一、引言
环境:64位Win 10中文版 + 64位Python 3.6.5 + 64位Office 2010

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



三、错误的引用方式

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

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

在上面的IDLE交互式窗口中,有两个导入语句和一个创建Word进程的语句,缺一不可。
注意,为了使用constants模块中预先定义的常量,我们用来创建Word进程使用的是EnsureDispatch,而不是Dispatch,也不是DispatchEx。
下面简单解释一下。
五、解释
一般情况下,我们看到的创建Word进程的代码有三种:
方式一:用 Dispatch
from win32com.client import Dispatchword = Dispatch("Word.Application")
方式二:用 DispatchEx
from win32com.client import DispatchExword = DispatchEx("Word.Application")
方式三:用 EnsureDispatch
from win32com.client import constantsfrom win32com.client.gencache import EnsureDispatchword = 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 dirnameimport sysprint(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进程毫无影响。
六、总结

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




