web-dev-qa-db-ja.com

なぜprintf()がPythonで奇妙な出力をするのですか?

LinuxのpythonコマンドラインでC関数printf()を使用しようとしました。それを機能させるために、ctypesをインポートしました。私の問題は次のとおりです。 CDLLのオブジェクトを作成して、ループでprintf()- functionを使用すると、非常に奇妙な出力が得られます。

_>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")
>>> for i in range(10):
...     libc.printf("%d", i)
...
01
11
21
31
41
51
61
71
81
91
>>>
_

ただし、関数内でこのループを呼び出すと、期待どおりに機能します。

_>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")
>>> def pr():
...     for i in range(10):
...         libc.printf("%d", i)
...     libc.printf("\n")
...
>>> pr()
0123456789
>>>
_

この動作の原因は推測できません...
私はPython 2.7.6 Linuxで問題があれば)を使用しています。

編集:

Pythonバージョン/オペレーティングシステムはこれに影響しません。詳細については、以下のPM 2Ringの答えを参照してください。Windowsでは、libcの初期化をlibc = ctypes.CDLL("msvcrt.dll")に変更するだけで、_.dll_はオプションです。関数を呼び出すよりも正しい出力を取得する別の方法は、printf()の戻り値を変数に保存することです。

_>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")  # "mscvrt.dll" on windows
>>> for i in range(10):
...     r = libc.printf("%d", i)
...
0123456789>>>
_

最後の改行を簡単に追加できるので、この機能は今でも気に入っています。

38
Aemyl

各番号の末尾にある余分な'1'sは、printfからの戻り値であり、印刷する文字数を返します。インタラクティブインタープリターで呼び出された関数の戻り値は自動的に出力されます(Noneでない限り)。

実際、インタラクティブインタープリターは、割り当てられていない非None式を出力します。そしてもちろん、これらの式に改行が追加され、最初のコードブロックの出力が別の行にある理由が説明されます。

pr関数にはreturnステートメントがないため、Noneを返すため、余分なものは出力されません。

86
PM 2Ring

PM 2Ringはこの質問に非常によく答えていますが、printfの動作、または非常に近いものがpython built-なので、ctypesの使用方法を学ぶために使用しない限り、Cライブラリバージョンを使用するのは非常に奇妙です。

しかし一方で、十分なpythonを使用してREPLがどのように機能するかを理解していないときにctypesを使用したいのは奇妙です。 ... years慢に聞こえるかもしれませんが、10年の経験があるpythonの経験があるので、実際にctypesを使う必要はありませんでした。

Pythonの文字列フォーマットには、2つの組み込みオプションがあります。

_print("%d" % (i,))
_

これは古いスタイルで、printfと非常によく似ています。

_print("{:d}".format(i))
_

これはpython 3の新機能であり、やや強力です。このサイトの違いに対処する questions があります。上記の両方の行はlibc.printf("%d\n", i)改行なしで印刷 も可能です。

「%」文字列フォーマットのCPython実装では、実際にはsprintf 内部 を使用します。

5
Amanda Ellaway