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

Aem*_*myl 38 python ctypes python-2.7

我试图printf()在Linux上的python命令行中使用C函数.为了完成这项工作,我导入了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
>>>
Run Code Online (Sandbox Code Playgroud)

但是,当我在函数内部调用此循环时,它按预期工作:

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

我猜不出是什么导致了这种行为......
如果重要的话,我在Linux上使用Python 2.7.6.

编辑:

Python版本/操作系统对此没有影响.有关详细信息,请参阅下面的PM 2Ring的答案.在Windows上,您只需将初始化更改libclibc = ctypes.CDLL("msvcrt.dll")where .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>>>
Run Code Online (Sandbox Code Playgroud)

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

PM *_*ing 85

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

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

您的pr函数没有return语句,因此返回None,因此不会打印额外的东西.

  • @Aemyl不,这是所有版本的标准(CPython)解释器和所有操作系统的标准.有_are_其他Python解释器/ IDE,但默认情况下,它们还以交互模式(AFAIK)运行时打印非``None`表达式的值,尽管它们也可能打印其他信息. (2认同)
  • 没有printf调用的同样的事情:`for i in range(10):1` (2认同)
  • 注意:`ipython`(包装CPython解释器的_very_常用替代交互式解释器,作为众多功能之一)更智能,并且不会在块中输出未分配表达式的结果.它仅输出未分配的单个表达式. (2认同)

Ama*_*way 5

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

但另一方面,ctypes当你没有使用足够的python知道REPL是如何工作的时候想要使用它是很奇怪的...冒着傲慢的风险,就像有10年python经验的人一样,我从来没有不得不用ctypes.

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

print("%d" % (i,))
Run Code Online (Sandbox Code Playgroud)

这是旧式的,与printf非常相似,而且

print("{:d}".format(i))
Run Code Online (Sandbox Code Playgroud)

这是python 3的新功能,并且功能更强大.有关于解决本网站差异的问题.以上两行都将输出相同的libc.printf("%d\n", i).也可以在没有换行的情况下进行打印.

CPython的实现"%"字符串格式化的实际使用sprintf的引擎盖下.