为什么printf()在python中给出一个奇怪的输出?

时间:2016-12-14 13:04:28

标签: python python-2.7 ctypes

我尝试在Linux上的python命令行中使用C函数printf()。为了完成这项工作,我导入了ctypes。我的问题是:如果我创建一个CDLL的对象以在循环中使用printf() - 函数,我得到一个非常奇怪的输出:

>>> 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
>>>

我无法猜出导致这种行为的原因......
如果重要的话,我在Linux上使用Python 2.7.6。

修改

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>>>

我仍然更喜欢这个功能,因为你可以更容易地添加一个结束的换行符。

2 个答案:

答案 0 :(得分:86)

每个数字末尾的额外'1'是来自printf的返回值,它返回它打印的字符数。将自动打印交互式解释器中调用的函数的返回值(除非它是None)。

实际上,交互式解释器会打印未分配的任何非None表达式。当然,它为这些表达式添加了一个换行符,这解释了为什么第一个代码块中的输出位于不同的行上。

您的pr函数没有返回语句,因此返回None,因此不会打印额外的内容。

答案 1 :(得分:5)

虽然PM 2Ring已经很好地回答了这个问题,但我认为值得指出的是,printf的行为或非常接近的行为可以作为内置的python使用,因此它可以用来实现。你真的很奇怪你正在使用C库版本,除非你正在使用它来学习如何使用ctypes,在这种情况下继续。

但另一方面,当你没有使用足够的python知道REPL是如何工作的时候想要使用ctypes是很奇怪的......冒着听起来很傲慢的风险,作为拥有10年python经验的人,我从未真正使用过ctypes

python中有两个用于字符串格式化的内置选项:

print("%d" % (i,))

这是旧样式,与printf和

非常相似
print("{:d}".format(i))

这是python 3的新功能,并且功能更强大。有questions解决了此网站上的差异。上述两行将与libc.printf("%d\n", i)输出相同。它也可以print without the newline

"%"的CPython实现字符串格式实际上使用sprintf under the hood