J'ai écrit un utilitaire de ligne de commande qui utilise getopt pour analyser les arguments donnés sur la ligne de commande. Je voudrais également qu'un nom de fichier soit un argument facultatif, comme c'est le cas dans d'autres utilitaires comme grep, cut etc. Donc, je voudrais qu'il ait l'utilisation suivante
tool -d character -f integer [filename]
Comment puis-je implémenter les éléments suivants?
En termes simples:
import sys
# parse command line
if file_name_given:
inf = open(file_name_given)
else:
inf = sys.stdin
À ce stade, vous utiliseriez inf
pour lire le fichier. Selon qu'un nom de fichier a été donné, cela se lit à partir du fichier donné ou de stdin.
Lorsque vous devez fermer le fichier, vous pouvez le faire:
if inf is not sys.stdin:
inf.close()
Cependant, dans la plupart des cas, il sera inoffensif de fermer sys.stdin
si vous en avez terminé.
Le module fileinput peut faire ce que vous voulez - en supposant que les arguments sans option sont dans args
alors:
import fileinput
for line in fileinput.input(args):
print line
Si args
est vide, alors fileinput.input()
lira à partir de stdin; sinon, il lit à partir de chaque fichier tour à tour, d'une manière similaire à while(<>)
de Perl.
J'aime l'idiome général de l'utilisation d'un gestionnaire de contexte, mais la solution (trop) triviale finit par fermer sys.stdin
Lorsque vous êtes en dehors de l'instruction with
, ce que je veux éviter.
Emprunter de cette réponse , voici une solution:
import sys
import contextlib
@contextlib.contextmanager
def _smart_open(filename, mode='Ur'):
if filename == '-':
if mode is None or mode == '' or 'r' in mode:
fh = sys.stdin
else:
fh = sys.stdout
else:
fh = open(filename, mode)
try:
yield fh
finally:
if filename is not '-':
fh.close()
if __== '__main__':
args = sys.argv[1:]
if args == []:
args = ['-']
for filearg in args:
with _smart_open(filearg) as handle:
do_stuff(handle)
Je suppose que vous pourriez obtenir quelque chose de similaire avec os.dup()
mais le code que j'ai préparé pour le faire s'est avéré être plus complexe et plus magique, alors que ce qui précède est quelque peu maladroit mais très simple .
Pour utiliser l'instruction with
de python, on peut utiliser le code suivant:
import sys
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f:
# read data using f
# ......
Je préfère utiliser "-" comme indicateur que vous devriez lire depuis stdin, c'est plus explicite:
import sys
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f:
pass # do something here
Pas une réponse directe mais liée.
Normalement, lorsque vous écrivez un script python, vous pouvez utiliser le package argparse
. Si tel est le cas, vous pouvez utiliser:
parser = argparse.ArgumentParser()
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'), default=sys.stdin)
'?'. Un argument sera consommé à partir de la ligne de commande si possible, et produit comme un seul élément. Si aucun argument de ligne de commande n'est présent, la valeur par défaut sera produite.
et ici nous définissons la valeur par défaut sur sys.stdin
;
donc s'il y a un fichier il le lira, et sinon il prendra l'entrée de stdin "Remarque: que nous utilisons l'argument positionnel dans l'exemple ci-dessus"
pour plus de visite: https://docs.python.org/2/library/argparse.html#nargs
Quelque chose comme:
if input_from_file:
f = open(file_name, "rt")
else:
f = sys.stdin
inL = f.readline()
while inL:
print inL.rstrip()
inL = f.readline()