Python PyPDF2-PDF编码问题

Python PyPDF2-PDF编码问题,python,encoding,Python,Encoding,我正在尝试使用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 __

我正在尝试使用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
你知道怎么解决那个问题吗

谢谢和问候
Peter

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

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

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

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

keylen = 128 / 8
... # later on in the code...
key = md5_hash[:keylen]
除法运算符在Python2.2中进行了更改,从Python3开始更改了其默认行为。简言之,“/”在Python2中表示floor division并返回int,但在Python3中表示true division并返回float。因此,Python2中的“keylen”应该是16,而Python3中的“keylen”应该是16.0。与int不同,float不能用于拼接数组,因此python3抛出了在计算md5_hash[:keylen]时看到的TypeError。Python2将毫无错误地运行它,因为keylen将是一个int

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


然而,随后在代码中会遇到第三个bug,这也与Python3兼容性有关。我不会通过描述来说明这一点。在我看来,对您的问题的简短回答是要么使用Python 2,要么修补各种代码兼容性问题,要么使用不同的Python PDF库,该库对Python 3有更好的支持(如果存在一个满足您特定要求的库)。

我觉得PyPDF2的当前版本(1.19截至本文撰写之日)在与Python 3的兼容性方面存在一些错误,这就是导致这两条错误消息的原因。GitHub for PyPDF2上的更改日志表明,Python 3支持是在1.16版本中添加的,该版本仅在3个半月前发布,因此可能尚未报告或修复此错误。GitHub还显示存在漏洞该项目的第三个分支专门用于Python 3.3支持,目前尚未合并回主分支

这两个错误都发生在PyPDF2模块的pdf.py文件中。发生的情况如下:

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

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

keylen = 128 / 8
... # later on in the code...
key = md5_hash[:keylen]
除法运算符在Python2.2中进行了更改,更改了从Python3开始的默认行为。简言之,“/”在Python2中表示floor除法并返回int,但在Python3中表示true除法并返回float。因此,“keylen”在Python2中为16,但在Python3中为16.0。与int不同,float不能用于拼接数组,因此Python3会抛出在计算md5_hash[:keylen]时看到的TypeError。Python2会无误地运行它,因为keylen是int

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


然而,在代码的后面,您可能会遇到第三个bug,也与Python 3的兼容性有关。我不会通过描述来详细说明这一点。在我看来,您的问题的简短答案是要么使用Python 2,要么修补各种代码兼容性问题,或者为Python使用另一个PDF库,它具有更好的兼容性支持Python 3(如果存在满足您特定要求的版本)。

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


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

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


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

谢谢Christian,这非常有帮助!如果您认为它是