3

私はこれと非常によく似た質問をしています。Django の Ubuntu サーバーで wkhtmltopdf を使用して pdf を作成しています。

from tempfile import *
from subprocess import Popen, PIPE

tempfile = gettempdir()+"/results.pdf"
papersize = 'Tabloid'
orientation = 'Landscape'
command_args = "wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl %s" %(orientation, papersize, tempfile)
popen = Popen(command_args, stdout=PIPE, stderr=PIPE)
pdf_contents = popen.stdout().read()
popen.terminate()
popen.wait()
response = HttpResponse(pdf_contents, mimetype='application/pdf')
return response

これにより、 popen = Popen... 行に「そのようなファイルまたはディレクトリはありません」というエラーが表示されます。だから私はその行を

popen = Popen(["sh", "-c", command_args], stdout=PIPE, stderr=PIPE)

そして今、pdf_contents =... 行に「'file' object is not callable」というエラーが表示されます。

また、 popen =... 行に .communicate() を追加しようとしましたが、その方法で pdf 出力を見つけることができないようです。command_args 行をコマンド ラインに入力すると、問題なく pdf が作成されることを追加する必要があります。誰かが私を正しい方向に向けることができますか?

4

4 に答える 4

3

wkhtmltopdfPopenそれを読む ためにPDFの内容を出力していません。pdf_contentsコマンドの出力が正しく含まれています (何もありません)。出力ファイルをクライアントに返す場合は、出力ファイルの内容を読み取る必要があります (以下を参照)。または、出力ファイルをスキップしてwkhtmltopdf、pdf の内容を直接出力する必要があります。

from tempfile import *
from subprocess import Popen, PIPE

tempfile = gettempdir()+"/results.pdf"
command_args = "/path/to/wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl %s" % ('Landscape', 'Tabloid', tempfile)
popen = Popen(["sh", "-c", command_args])
popen.wait()
f = open(tempfile, 'r')
pdf_contents = f.read()
f.close()

return HttpResponse(pdf_contents, mimetype='application/pdf')
于 2011-03-24T19:43:39.500 に答える
2

Python は wkhtmltopdf の場所を認識していないため、最初のバージョンは失敗します。Python はパスをチェックしません。2番目のバージョンは、コマンドをシェルに渡します。シェルはそれを処理します。shell=True 引数を渡すと、同じ効果が得られます。

2番目の問題(他の人が指摘したように)は、すべきでないときに stdout() を呼び出すことです。

3 番目の問題は、wkhtmltopdf コマンドが間違っていることです。あなたがやっている:

wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl tempfile/results.pdf

代わりにあなたは合格するべきです

wkhtmltopdf -O %s -s %s -T 0 -R 0 -B 0 -L 0 http://pdfurl -

そうすれば、 wkhtmltopdf は出力を標準出力に書き込み、それを読み取ることができます。別の - をソースとして渡すと、標準入力経由で html を送信できます。

于 2011-03-24T19:47:26.673 に答える
1

あなたが得て'file' object is not callableいる理由は、あなたがあなたのpopenオブジェクトを手に入れたらstdout、それはメソッドではなくファイルハンドルだからです。それを呼ばないでください、ただそれを使ってください:

popen = Popen(command_args, stdout=PIPE, stderr=PIPE)
pdf_contents = popen.stdout.read()
于 2011-03-24T18:58:41.393 に答える
0

変更を検討することをお勧めします

popen = Popen(command_args, stdout=PIPE, stderr=PIPE)
pdf_contents = popen.stdout().read()
# ...
response = ...

pdf_contents = subprocess.check_output(command_args.split())
response = ...

または古いバージョン:

process = Popen(command_args.split(), stdout=PIPE, stderr=PIPE)
pdf_contents = process.stdout.read()
response = ...

check_output関数を確認することをお勧めします。

編集:また、terminate()を呼び出さないでください。プロセスが完了するのを待たずにプロセスを強制終了し、PDFが破損する可能性があります。プロセスが完了するのを待つ(したがって、出力する必要があるすべてを出力する)ので、ほとんどの場合、wait()を使用するだけで済みます。check_output()関数を使用する場合、プロセスが「デフォルト」で完了するのを待つため、心配する必要はありません。

それ以外は、モジュールと同じ名前の変数に名前を付けること(私はtempfileについて話している)は悪い考えです。tmpfileに変更し、NamedTemporaryFileをチェックアウトすることをお勧めします。これは、現在行っていることよりも安全に使用できるためです。

于 2011-03-24T18:57:26.203 に答える