1

我正在尝试使用 PyPDF2 在 Python 3.3.2 下加密 PDF 文件。

代码非常简单:

password = 'password';
# password = password.encode('utf-8')
PDFout.encrypt(user_pwd=password,owner_pwd=password)

但是我收到以下错误,具体取决于编码是打开还是关闭:

on: TypeError: slice indices must be integers or None or have an __index__ method

off: TypeError: Can't convert 'bytes' object to str implicitly

你会知道如何解决这个问题吗?

感谢和问候彼得

4

2 回答 2

1

在我看来,PyPDF2 的当前版本(撰写本文时为 1.19)存在一些与 Python 3 兼容性有关的错误,这就是导致这两条错误消息的原因。GitHub 上 PyPDF2 的更改日志表明 Python 3 支持是在 1.16 版中添加的,该版本仅在 3 1/2 个月前发布,因此可能尚未报告或修复此错误。GitHub 还显示该项目有一个专门用于支持 Python 3.3 的分支,目前尚未合并回主分支。

这两个错误都发生在 PyPDF2 模块的 pdf.py 文件中。这是正在发生的事情:

PyPDF2 模块创建一些额外的字节作为填充并将其与您的密码连接起来。如果 Python 版本小于 3,则将填充创建为字符串文字。如果版本为 3 或更高,则填充使用“latin-1”编码进行编码。在 Python 3 中,这意味着填充是一个字节对象,并且将其与字符串对象(您的密码)连接会产生您看到的 TypeError。在 Python 2 下,连接会起作用,因为两个对象都是相同的类型。

当您使用“utf-8”对密码进行编码时,您可以解决该问题,因为在这种情况下密码和填充都是字节对象。但是,您最终会在模块的后面遇到第二个错误。pdf.py 文件创建并使用一个变量“keylen”,如下所示:

keylen = 128 / 8
... # later on in the code...
key = md5_hash[:keylen]

除法运算符在 Python 2.2 中发生了变化,从 Python 3 开始改变了它的默认行为。简而言之,“/”在 Python 2 中表示地板除法并返回一个 int,但在 Python 3 中它表示真正的除法并返回一个浮点数。因此,“keylen”在 Python 2 中为 16,而在 Python 3 中为 16.0。与 int 不同,浮点数不能用于拼接数组,因此 Python 3 会抛出您在计算 md5_hash[:keylen] 时看到的 TypeError。Python 2 将毫无错误地运行它,因为 keylen 将是一个 int。

您可以通过更改模块的源代码以使用“//”运算符来解决第二个问题(这意味着除法并在 Python 2 和 3 中返回一个 int):

keylen = 128 // 8

但是,您稍后会在代码中遇到第三个错误,也与 Python 3 兼容性有关。我不会通过描述来强调这一点。那么,据我所知,对您的问题的简短回答是要么使用 Python 2,要么修补各种代码兼容性问题,或者为 Python 使用不同的 PDF 库,它对 Python 3 有更好的支持(如果存在满足您的特定要求)。

于 2013-10-15T16:41:19.283 回答
0

尝试安装最新版本的PyPDF2 - 它现在完全支持 Python 3!

似乎在 1.16 中添加了“一些”支持,但并未涵盖所有功能。现在,Py 3 应该与这个库完全兼容。

于 2014-08-12T20:44:51.513 回答