我尝试在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>>>
我仍然更喜欢这个功能,因为你可以更容易地添加一个结束的换行符。
答案 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。