J'essaie de relever certains des défis du golf de code , mais ils nécessitent tous la saisie de l'entrée stdin
. Comment puis-je obtenir cela en Python?
1474
J'essaie de relever certains des défis du golf de code , mais ils nécessitent tous la saisie de l'entrée stdin
. Comment puis-je obtenir cela en Python?
Vous pouvez utiliser le fileinput
module:
import fileinput
for line in fileinput.input():
pass
fileinput
parcourra toutes les lignes de l'entrée spécifiées en tant que noms de fichiers donnés dans les arguments de ligne de commande, ou l'entrée standard si aucun argument n'est fourni.
Remarque: line
contiendra une nouvelle ligne de fin; pour l'enlever utiliserline.rstrip()
Il y a plusieurs façons de le faire.
sys.stdin
est un objet de type fichier sur lequel vous pouvez appeler des fonctionsread
oureadlines
si vous voulez tout lire ou vous voulez tout lire et le diviser automatiquement par saut de ligne. (Vous devez pourimport sys
que cela fonctionne.)Si vous souhaitez inviter l'utilisateur à entrer des informations, vous pouvez l'utiliser
raw_input
dans Python 2.X et uniquementinput
dans Python 3.Si vous souhaitez simplement lire les options de ligne de commande, vous pouvez y accéder via la liste sys.argv .
Vous trouverez probablement cet article de Wikibook sur les E / S en Python pour être également une référence utile.
la source
Notez que cela inclura un caractère de nouvelle ligne à la fin. Pour supprimer la nouvelle ligne à la fin, utilisez
line.rstrip()
comme l'a dit @brittohalloran.la source
\r\n
fins de lignePython a également des fonctions intégrées
input()
etraw_input()
. Voir la documentation Python sous Fonctions intégrées .Par exemple,
ou
la source
Voici l' apprentissage de Python :
Sur Unix, vous pouvez le tester en faisant quelque chose comme:
Sous Windows ou DOS, vous feriez:
la source
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. voirwc-l.py
cat
ici est redondante. L'invocation correcte pour les systèmes Unix estpython countlines.py < countlines.py
.readlines()
. Les objets fichier sont destinés à être itérés sans matérialiser toutes les données en mémoire.Vous pouvez utiliser:
sys.stdin
- Un objet de type fichier - appelsys.stdin.read()
à tout lire.input(prompt)
- passez-lui une invite facultative pour la sortie, il lit de stdin jusqu'à la première nouvelle ligne, qu'il supprime. Vous devriez le faire à plusieurs reprises pour obtenir plus de lignes, à la fin de l'entrée, il déclenche EOFError. (Probablement pas génial pour le golf.) En Python 2, c'est le casrawinput(prompt)
.open(0).read()
- En Python 3, la fonction intégréeopen
accepte les descripteurs de fichiers (entiers représentant les ressources d'E / S du système d'exploitation), et 0 est le descripteur destdin
. Il renvoie un objet semblable à un fichiersys.stdin
- probablement votre meilleur pari pour le golf. En Python 2, c'est le casio.open
.open('/dev/stdin').read()
- similaire àopen(0)
, fonctionne sur Python 2 et 3, mais pas sur Windows (ni même Cygwin).fileinput.input()
- renvoie un itérateur sur les lignes de tous les fichiers répertoriés danssys.argv[1:]
, ou stdin s'il n'est pas indiqué. Utilisez comme''.join(fileinput.input())
.Les deux
sys
etfileinput
doivent être importés, respectivement, bien sûr.sys.stdin
Exemples rapides compatibles avec Python 2 et 3, Windows, UnixVous avez juste besoin
read
desys.stdin
, par exemple, si vous dirigez des données vers stdin:Nous pouvons voir que
sys.stdin
c'est en mode texte par défaut:exemple de fichier
Supposons que vous ayez un fichier,
inputs.txt
nous pouvons l'accepter et le réécrire:Réponse plus longue
Voici une démo complète et facilement reproductible, utilisant deux méthodes, la fonction intégrée,
input
(à utiliserraw_input
en Python 2), etsys.stdin
. Les données ne sont pas modifiées, le traitement est donc une non-opération.Pour commencer, créons un fichier pour les entrées:
Et en utilisant le code que nous avons déjà vu, nous pouvons vérifier que nous avons créé le fichier:
Voici l'aide
sys.stdin.read
de Python 3:Fonction intégrée,
input
(raw_input
en Python 2)La fonction intégrée
input
lit depuis l'entrée standard jusqu'à une nouvelle ligne, qui est supprimée (complémentprint
, qui ajoute une nouvelle ligne par défaut.) Cela se produit jusqu'à ce qu'elle obtienne EOF (End Of File), moment auquel elle augmenteEOFError
.Ainsi, voici comment vous pouvez utiliser
input
en Python 3 (ouraw_input
en Python 2) pour lire à partir de stdin - nous créons donc un module Python que nous appelons stdindemo.py:Et imprimons-le de nouveau pour nous assurer qu'il est comme prévu:
Encore une fois,
input
lit jusqu'à la nouvelle ligne et la retire essentiellement de la ligne.print
ajoute une nouvelle ligne. Ainsi, alors qu'ils modifient tous les deux l'entrée, leurs modifications s'annulent. (Ils sont donc essentiellement complémentaires les uns des autres.)Et quand
input
obtient le caractère de fin de fichier, il déclenche EOFError, que nous ignorons puis quittons le programme.Et sous Linux / Unix, nous pouvons diriger depuis cat:
Ou nous pouvons simplement rediriger le fichier depuis stdin:
Nous pouvons également exécuter le module en tant que script:
Voici l'aide sur le module intégré
input
de Python 3:sys.stdin
Ici, nous faisons un script de démonstration en utilisant
sys.stdin
. Le moyen efficace d'itérer sur un objet de type fichier est d'utiliser l'objet de type fichier comme itérateur. La méthode complémentaire pour écrire sur stdout à partir de cette entrée consiste simplement à utilisersys.stdout.write
:Imprimez-le pour vous assurer qu'il a l'air correct:
Et rediriger les entrées dans le fichier:
Joué dans une commande:
Descripteurs de fichiers pour le golf
Étant donné que les descripteurs de fichiers pour
stdin
etstdout
sont respectivement 0 et 1, nous pouvons également les transmettre àopen
Python 3 (pas 2, et notons que nous avons toujours besoin du «w» pour écrire sur stdout).Si cela fonctionne sur votre système, cela supprimera plus de caractères.
Python 2 le
io.open
fait également, mais l'importation prend beaucoup plus de place:Répondre à d'autres commentaires et réponses
Un commentaire suggère
''.join(sys.stdin)
pour le golf, mais c'est en fait plus long que sys.stdin.read () - en plus Python doit créer une liste supplémentaire en mémoire (c'est comme ça que çastr.join
marche quand on ne lui donne pas de liste) - pour le contraste:La première réponse suggère:
Mais, depuis
sys.stdin
implémente l'API de fichier, y compris le protocole itérateur, c'est exactement la même chose que ceci:Une autre réponse ne suggère cela. N'oubliez pas que si vous le faites dans un interpréteur, vous devrez faire Ctrl- dsi vous êtes sous Linux ou Mac, ou Ctrl- zsous Windows (après Enter) pour envoyer le caractère de fin de fichier au processus. En outre, cette réponse suggère
print(line)
- ce qui ajoute un'\n'
à la fin - à laprint(line, end='')
place (si en Python 2, vous en aurez besoinfrom __future__ import print_function
).Le vrai cas d'utilisation pour
fileinput
est de lire une série de fichiers.la source
La réponse proposée par d'autres:
est très simple et pythonique, mais il faut noter que le script attendra EOF avant de commencer à itérer sur les lignes d'entrée.
Cela signifie que
tail -f error_log | myscript.py
les lignes ne seront pas traitées comme prévu.Le script correct pour un tel cas d'utilisation serait:
MISE
À JOUR D'après les commentaires, il a été effacé que sur python 2 seulement, il peut y avoir un tampon impliqué, de sorte que vous finissez par attendre que le tampon se remplisse ou EOF avant que l'appel d'impression ne soit émis.
la source
for line in sys.stdin:
motif n'attend pas EOF. Mais si vous testez sur de très petits fichiers, les réponses peuvent être mises en mémoire tampon. Testez avec plus de données pour voir qu'il lit les résultats intermédiaires.print line
ne s'est pas réveillé en 3.1.3, mais leprint(line)
fait.for line in sys.stdin:
ne "bloque pas jusqu'à EOF". Il existe un bogue de lecture anticipée dans Python 2 qui retarde les lignes jusqu'à ce que le tampon correspondant soit plein. Il s'agit d'un problème de mise en mémoire tampon qui n'est pas lié à l'EOF. Pour contourner ce problème, utilisezfor line in iter(sys.stdin.readline, ''):
(utiliserio.open()
pour les fichiers ordinaires). Vous n'en avez pas besoin en Python 3.Cela fera écho de l'entrée standard à la sortie standard:
la source
En s'appuyant sur toutes les réponses à l'aide
sys.stdin
, vous pouvez également faire quelque chose comme ce qui suit pour lire à partir d'un fichier d'arguments s'il existe au moins un argument, et revenir à stdin sinon:et l'utiliser comme
ou
ou même
Cela ferait en sorte que votre script Python se comporte comme de nombreux programmes GNU / Unix tels que
cat
,grep
etsed
.la source
argparse
est une solution simpleExemple compatible avec les versions 2 et 3 de Python:
Vous pouvez exécuter ce script de plusieurs manières:
1. Utilisation
stdin
ou plus court en remplaçant
echo
par ici la chaîne :2. Utilisation d'un argument de nom de fichier
3. Utilisation
stdin
via le nom de fichier spécial-
la source
add_argument('--in'
, puis diriger vers le script et l'ajouter--in -
à la ligne de commande. PSin
n'est pas un très bon nom pour une variable / un attribut.in
n'est pas seulement un mauvais nom pour une variable, c'est illégal.args.in.read()
générera une erreur InvalidSyntax en raison duin
mot clé réservé. Peut simplement renommer pourinfile
aimer les documents python argparse: docs.python.org/3/library/…La puce de code suivante vous aidera (elle lira tout le blocage de stdin
EOF
dans une seule chaîne):la source
Je suis assez étonné que personne n'ait mentionné ce hack jusqu'à présent:
en python2, vous pouvez abandonner l'
set()
appel, mais il s'exprimerait de toute façonla source
readlines
ce fractionnement en lignes, puis àjoin
nouveau? Vous pouvez simplement écrireprint(sys.stdin.read())
write
retoursNone
, et la taille définie ne seraient jamais supérieurs à 1 (=len(set([None]))
)Essaye ça:
et vérifiez-le avec:
la source
Vous pouvez lire à partir de stdin puis stocker les entrées dans des "données" comme suit:
la source
data = sys.stdin.read()
, sans problème de concaténations répétées de chaînes.Lisez à partir de
sys.stdin
, mais pour lire les données binaires sur Windows , vous devez être très prudent, carsys.stdin
il est ouvert en mode texte et il sera corrompu\r\n
en les remplaçant par\n
.La solution consiste à définir le mode sur binaire si Windows + Python 2 est détecté et sur Python 3 à utiliser
sys.stdin.buffer
.la source
J'utilise la méthode suivante, elle retourne une chaîne de stdin (je l'utilise pour l'analyse json). Il fonctionne avec pipe et prompt sur Windows (pas encore testé sur Linux). Lorsque vous y êtes invité, deux sauts de ligne indiquent la fin de la saisie.
la source
Le problème que j'ai avec la solution
est que si vous ne transmettez aucune donnée à stdin, il se bloquera pour toujours. C'est pourquoi j'aime cette réponse : vérifiez s'il y a d'abord des données sur stdin, puis lisez-les. C'est ce que j'ai fini par faire:
la source
select
est appelée; ou vous pourriez également rencontrer des problèmes si stdin est connecté à un fichier sur un support lent (réseau, CD, bande, etc.). Vous avez dit que "si vous ne transmettez aucune donnée à stdin, elle se bloquera pour toujours". est un problème , mais je dirais que c'est une fonctionnalité . La plupart des programmes CLI (par exemplecat
) fonctionnent de cette façon, et ils devraient le faire. EOF est la seule chose sur laquelle vous devez compter pour détecter la fin de l'entrée.J'ai eu quelques problèmes lorsque cela fonctionnait pour la lecture sur les sockets raccordées. Lorsque le socket a été fermé, il a commencé à renvoyer une chaîne vide dans une boucle active. C'est donc ma solution (que je n'ai testé que sous Linux, mais j'espère que cela fonctionne dans tous les autres systèmes)
Donc, si vous commencez à écouter sur un socket, cela fonctionnera correctement (par exemple en bash):
Et vous pouvez l'appeler avec telnet ou simplement pointer un navigateur vers localhost: 12345
la source
Concernant ceci:
for line in sys.stdin:
Je viens de l'essayer sur python 2.7 (suite à la suggestion de quelqu'un d'autre) pour un très gros fichier, et je ne le recommande pas, précisément pour les raisons mentionnées ci-dessus (rien ne se passe depuis longtemps).
Je me suis retrouvé avec une solution légèrement plus pythonique (et cela fonctionne sur des fichiers plus gros):
Ensuite, je peux exécuter le script localement en tant que:
la source
sys.stdin
comme argument de ligne de commande au script.sys.stdin
comme argument de ligne de commande au script? Les arguments sont des chaînes et les flux sont des objets de type fichier, ils ne sont pas identiques.sys.stdin
est un objet de type fichierPour Python 3, ce serait:
Il s'agit essentiellement d'une forme simple de cat (1), car il n'ajoute pas de nouvelle ligne après chaque ligne. Vous pouvez l'utiliser (après avoir marqué le fichier exécutable en utilisant
chmod +x cat.py
par exemple:la source
Il y a
os.read(0, x)
qui lit xbytes à partir de 0 qui représente stdin. Il s'agit d'une lecture sans tampon, de niveau plus bas que sys.stdin.read ()la source
Lorsque vous utilisez la
-c
commande, de manière délicate, au lieu de lire lestdin
(et plus flexible dans certains cas), vous pouvez également passer une commande de script shell à votre commande python en plaçant la commande sell entre guillemets entre parenthèses commencée par$
signe.par exemple
Cela comptera le nombre de lignes du fichier historique de Goldendict.
la source