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 との互換性に関するいくつかのバグがあり、それが両方のエラー メッセージの原因になっているようです。PyPDF2 の GitHub の変更ログは、Python 3 サポートがバージョン 1.16 で追加されたことを示しています。バージョン 1.16 はわずか 3 か月半前にリリースされたため、このバグがまだ報告されていないか、修正されていない可能性があります。GitHub は、このプロジェクトの Python 3.3 サポート専用のブランチがあることも示していますが、現在はメイン ブランチにマージされていません。

どちらのエラーも、PyPDF2 モジュールの pdf.py ファイルで発生します。何が起こっているかは次のとおりです。

PyPDF2 モジュールは、余分なバイトをパディングとして作成し、それをパスワードと連結します。Python バージョンが 3 未満の場合、パディングは文字列リテラルとして作成されます。バージョンが 3 以上の場合、パディングは「latin-1」エンコーディングを使用してエンコードされます。Python 3 では、これはパディングがバイト オブジェクトであることを意味し、それを文字列オブジェクト (パスワード) と連結すると、見た TypeError が生成されます。Python 2 では、両方のオブジェクトが同じ型になるため、連結は機能します。

「utf-8」を使用してパスワードをエンコードすると、その場合、パスワードとパディングの両方がバイト オブジェクトになるため、この問題は解決します。ただし、モジュールの後半で 2 つ目のバグに遭遇することになります。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 では真の除算を意味し、float を返します。したがって、「keylen」は Python 2 では 16 になりますが、Python 3 では代わりに 16.0 になります。int とは異なり、浮動小数点数は配列を結合するために使用できないため、Python 3 は md5_hash[:keylen] が評価されたときに見た TypeError をスローします。keylen は int であるため、Python 2 はこれをエラーなしで実行します。

この 2 番目の問題は、モジュールのソース コードを変更して "//" 演算子を使用することで解決できます (これは、Python 2 と 3 の両方で床除算を意味し、int を返します)。

keylen = 128 // 8

ただし、コードの後半で、これも Python 3 の互換性に関連する 3 番目のバグに遭遇します。私はそれを説明することによって要点を詳しく説明しません. あなたの質問に対する簡単な答えは、私が見る限り、Python 2を使用するか、さまざまなコードの互換性の問題にパッチを当てるか、Python 3をより適切にサポートするPython用の別のPDFライブラリを使用することです(存在する場合)特定の要件を満たしています)。

于 2013-10-15T16:41:19.283 に答える