web-dev-qa-db-fra.com

Pourquoi printf () donne-t-il une sortie étrange en python?

J'ai essayé d'utiliser la fonction C printf() dans la ligne de commande python sous Linux. Pour que cela fonctionne, j'ai importé ctypes. Mon problème est le suivant: Si je crée un objet de CDLL pour utiliser la fonction printf()- dans une boucle, j'obtiens une sortie vraiment bizarre:

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

Cependant, lorsque j'appelle cette boucle dans une fonction, cela fonctionne comme prévu:

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

Je ne peux pas deviner ce qui cause ce comportement ...
J'utilise Python 2.7.6 sous Linux si cela est important.

MODIFIER:

La version/le système d'exploitation Python n'a aucune influence sur cela. Voir PM 2La réponse de Ring ci-dessous pour plus de détails. Sous Windows, il vous suffit de modifier l'initialisation de libc en libc = ctypes.CDLL("msvcrt.dll").dll Est facultatif. Une autre façon d'obtenir la sortie correcte que d'appeler une fonction serait de stocker la valeur de retour de printf() dans une variable:

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

Je préfère toujours la fonction, car vous pouvez ajouter un saut de ligne de conclusion plus facilement.

38
Aemyl

Ces extra '1's à la fin de chaque nombre sont la valeur de retour de printf, qui renvoie le nombre de caractères qu'il imprime. La valeur de retour d'une fonction appelée dans l'interpréteur interactif est automatiquement imprimée (sauf si elle est None).

En fait, l'interpréteur interactif imprime toute expression nonNone qui n'est pas affectée. Et bien sûr, il ajoute une nouvelle ligne à ces expressions, ce qui explique pourquoi la sortie de votre premier bloc de code se trouve sur des lignes distinctes.

Votre fonction pr n'a pas d'instruction de retour, elle renvoie donc None, et donc aucun élément supplémentaire n'est imprimé.

86
PM 2Ring

Alors que PM 2Ring a très bien répondu à la question, je pense qu'il vaut la peine de souligner que le comportement de printf, ou quelque chose de très proche, est disponible sous la forme python built- dans, il est donc assez étrange que vous utilisiez la version de la bibliothèque C, sauf si vous l'utilisez pour apprendre à utiliser ctypes, auquel cas continuez.

Mais d'un autre côté, il est étrange de vouloir utiliser ctypes quand vous n'en avez pas assez utilisé python pour savoir comment fonctionne le REPL ... au risque de paraître arrogant, comme quelqu'un avec 10 ans d'expérience python, je n'ai jamais vraiment eu à utiliser ctypes pour le moment.

Il existe deux options intégrées pour le formatage des chaînes en python:

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

qui est l'ancien style, et très similaire à printf, et

print("{:d}".format(i))

qui est nouveau pour python 3, et est un peu plus puissant. Il y a questions adressant les différences sur ce site. Les deux lignes ci-dessus sortiront de manière identique à libc.printf("%d\n", i). Il est également possible de imprimer sans la nouvelle ligne .

L'implémentation CPython du formatage de chaîne "%" utilise en fait sprintf sous le capot .

5
Amanda Ellaway