Enregistrer automatiquement les arguments de fonction dans argparse en Python

introduction

argparse est un package utile pour créer des scripts de ligne de commande avec des arguments optionnels en python. C'est un package pratique, mais j'ai fait des dizaines de fois pour faire des arguments fermement avec des fonctions et les réécrire avec argparse, et j'étais motivé par l'idée que ce travail était inutile. Alors automatisons-le.

Différence par rapport au clic

On m'a dit dans le commentaire que je faisais la même chose que click, et je pensais avoir réinventé à nouveau la roue pendant un moment, mais quand j'ai essayé d'utiliser click, il semble que c'est différent, alors je vais l'ajouter .. La fonction de click est que la définition des options et des arguments écrits par argparse peut être distribuée à chaque fonction en tant que décorateur, et les arguments de la fonction ne sont pas automatiquement enregistrés comme options. Après tout, au lieu de add_argument, écrivez simplement @ click.option et le contenu que vous écrivez ne change pas beaucoup. Cela ne veut pas dire que le clic est mauvais, c'est un but différent. Click est un excellent package en termes d'organisation et d'écriture et d'amélioration de la lisibilité. Cependant, cette fois, je l'ai écrit à peu près dans le but "d'enregistrer automatiquement tous les arguments de la fonction créée en tant qu'arguments de ligne de commande!", Donc la considération suivante peut encore être utile pour un script simple mais variable. inconnue··. Au contraire, j'ai essayé d'utiliser Click et j'ai trouvé de nombreuses fonctions qui pourraient être utiles dans d'autres scènes, donc je résumerai le contenu séparément la prochaine fois.

Analyse des arguments de fonction

Un package appelé inspect est utilisé pour l'analyse des arguments de fonction. Puisque j'utilise python2.7, j'utilise l'ancien getargspec, mais pour python3, utilisez getfullargspec.

from inspect import getargspec

def func(aaa=1, bbb="a", ccc=[1,2,3,]):
	pass

args, varargs, keywords, defaults = getargspec(func)

print 'args: ', args
print 'varargs', varargs
print 'keywords: ', keywords
print 'defaults: ', defaults

Lorsque j'exécute ce qui précède, j'obtiens la sortie suivante:

args:  ['aaa', 'bbb', 'ccc']
varargs None
keywords:  None
defaults:  (1, 'a', [1, 2, 3])

Enregistrement automatique des arguments dans argparse

Utilisez ces informations pour enregistrer automatiquement les options argparse.

from inspect import getargspec

def func(aaa=1, bbb="a", ccc=[1,2,3,]):
	pass

args, varargs, keywords, defaults = getargspec(func)

import argparse

parser = argparse.ArgumentParser()
for arg, default in zip(args, defaults):
	parser.add_argument(
		'--' + arg,
		default=default,
		type=type(default)
	)

print parser.parse_args()

Faire ce qui précède vous donnera l'objet d'espace de noms suivant:

Namespace(aaa=1, bbb='a', ccc=[1, 2, 3])

Prise en charge des arguments de longueur variable

En fait, dans le cas ci-dessus, la correspondance avec des arguments de longueur variable n'est pas suffisante. Vous trouverez ci-dessous le code qui ajoute la prise en charge des arguments de longueur variable, bien que ce soit un peu plus long.

from inspect import getargspec

def func(aaa=1, bbb="a", ccc=[1,2,3,]):
	pass

args, varargs, keywords, defaults = getargspec(func)

import argparse

parser = argparse.ArgumentParser()
for arg, default in zip(args, defaults):
	if type(default) is tuple or type(default) is list:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default),
			nargs='+'
		)
	else:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default)
		)

Plus précisément, si l'argument est une liste ou un tapple, ajoutez l'argument nargs à add_argument.

Correspondance à la valeur booléenne, activer, désactiver ...

Dans le cas d'un argument de valeur booléenne, la valeur est déterminée de manière unique lorsqu'elle n'est pas la valeur par défaut, il est donc courant de spécifier l'acronyme disable, enable au lieu de spécifier True, False pour en faire une option qui ne prend pas de valeur. .. En incluant cette correspondance, cela devient comme suit.

from inspect import getargspec


def func(aaa=1, bbb="a", ccc=[1,2,3,], ddd=True, eee=False):
	pass

args, varargs, keywords, defaults = getargspec(func)

import argparse

parser = argparse.ArgumentParser()
for arg, default in zip(args, defaults):
	if type(default) is tuple or type(default) is list:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default),
			nargs='+'
		)
	elif type(default) is bool and default:
		parser.add_argument(
			'--disable_' + arg,
			dest=arg,
			default=default,
			action="store_false"
		)
	elif type(default) is bool and not default:
		parser.add_argument(
			'--enable_' + arg,
			dest=arg,
			default=default,
			action="store_true"
		)
	else:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default)
		)

Prise en charge d'argument qui n'a pas de valeur par défaut

Enfin, les arguments qui n'ont pas de valeurs par défaut sont également pris en charge. Cependant, gardez à l'esprit que cet argument est reconnu comme une chaîne car son type est inconnu.

from inspect import getargspec

def func(x, aaa=1, bbb="a", ccc=[1,2,3,], ddd=True, eee=False):
	pass

args, varargs, keywords, defaults = getargspec(func)

print 'args: ', args
print 'varargs', varargs
print 'keywords: ', keywords
print 'defaults: ', defaults

parser = argparse.ArgumentParser()

while len(args) > len(defaults):
	l = list(defaults)
	l.insert(0, None)
	defaults = tuple(l)
	
for arg, default in zip(args, defaults):
	if default is None:
		parser.add_argument(dest=arg)
	elif type(default) is tuple or type(default) is list:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default),
			nargs='+'
		)
	elif type(default) is bool and default:
		parser.add_argument(
			'--disable_' + arg,
			dest=arg,
			default=default,
			action="store_false"
		)
	elif type(default) is bool and not default:
		parser.add_argument(
			'--enable_' + arg,
			dest=arg,
			default=default,
			action="store_true"
		)
	else:
		parser.add_argument(
			'--' + arg,
			default=default,
			type=type(default)
		)

print parser.parse_args()

Conclusion

En utilisant inspect et argparse, il était possible de définir automatiquement l'argument de la fonction sur l'argument d'argparse. La version finale du code est jointe ci-dessous.

extract_arguments.py


#!/usr/bin/env python

import argparse
from inspect import getargspec

def set_arguments(parser, func):
	args, varargs, keywords, defaults = getargspec(func)

	print 'args: ', args
	print 'varargs', varargs
	print 'keywords: ', keywords
	print 'defaults: ', defaults

	while len(args) > len(defaults):
		l = list(defaults)
		l.insert(0, None)
		defaults = tuple(l)

	for arg, default in zip(args, defaults):
		if default is None:
			parser.add_argument(dest=arg)
		elif type(default) is tuple or type(default) is list:
			parser.add_argument(
				'--' + arg,
				default=default,
				type=type(default),
				nargs='+'
			)
		elif type(default) is bool and default:
			parser.add_argument(
				'--disable_' + arg,
				dest=arg,
				default=default,
				action="store_false"
			)
		elif type(default) is bool and not default:
			parser.add_argument(
				'--enable_' + arg,
				dest=arg,
				default=default,
				action="store_true"
			)
		else:
			parser.add_argument(
				'--' + arg,
				default=default,
				type=type(default)
			)
	return parser

def func(x, aaa=1, bbb="a", ccc=[1,2,3,], ddd=True, eee=False):
	pass


parser = argparse.ArgumentParser()
parser = set_arguments(parser, func)
print parser.parse_args()

Voici les décorateurs pour plus de commodité.

register_arguments.py


#!/usr/bin/env python

import argparse
from inspect import getargspec

def register_arguments(parser, func):
	args, varargs, keywords, defaults = getargspec(func)
	while len(args) > len(defaults):
		l = list(defaults)
		l.insert(0, None)
		defaults = tuple(l)

	for arg, default in zip(args, defaults):
		if default is None:
			parser.add_argument(dest=arg)
		elif type(default) is tuple or type(default) is list:
			parser.add_argument(
				'--' + arg,
				default=default,
				type=type(default),
				nargs='+'
			)
		elif type(default) is bool and default:
			parser.add_argument(
				'--disable_' + arg,
				dest=arg,
				default=default,
				action="store_false"
			)
		elif type(default) is bool and not default:
			parser.add_argument(
				'--enable_' + arg,
				dest=arg,
				default=default,
				action="store_true"
			)
		else:
			parser.add_argument(
				'--' + arg,
				default=default,
				type=type(default)
			)
	return parser

def register_argparse(parser):
	def wrapper(f):
		register_arguments(parser, f)
		return f
	return wrapper

if __name__ == '__main__':
	parser = argparse.ArgumentParser()

	@register_argparse(parser)
	def func(x, aaa=1, bbb="a", ccc=[1,2,3,], ddd=True, eee=False):
		pass

	print parser.parse_args()

Lorsque ce qui précède est exécuté, la sortie suivante est sortie.

$ python ./register_argments.py a
Namespace(aaa=1, bbb='a', ccc=[1, 2, 3], ddd=True, eee=False, x='a')

Recommended Posts

Enregistrer automatiquement les arguments de fonction dans argparse en Python
Notation inclusive dans l'argument de la fonction Python
Précautions lors de l'attribution de valeurs par défaut aux arguments dans les définitions de fonctions Python
À propos des arguments de fonction (python)
Comment recevoir des arguments de ligne de commande en Python
Essayez auto pour évaluer automatiquement Enum dans Python 3.6
Python: à propos des arguments de fonction
[Route vers Python intermédiaire] Définir la fonction __getattr__ dans la classe
Définissez les arguments mot-clés du constructeur sur les attributs fictifs en Python
Exécuter la fonction Python à partir de Powershell (comment passer des arguments)
Créer une fonction en Python
Pour vider stdout en Python
Utiliser la fonction de rappel en Python
Fonction ntile (décile) en python
Connectez-vous au site Web en Python
Recevoir des arguments d'exécution dans Python 2.7
Comment utiliser Python Argparse
Modélisation de fonctions non linéaires en Python
Dessiner la fonction Yin en python
Parler avec Python [synthèse vocale]
Fonction immédiate (lie) en python
Comment développer en Python
Publier sur Slack en Python
Créez un bot Mastodon avec une fonction pour répondre automatiquement avec Python
Comment échantillonner à partir de n'importe quelle fonction de densité de probabilité en Python
Pour renvoyer char * dans une fonction de rappel à l'aide de ctypes en Python
J'ai essayé d'implémenter la fonction d'envoi de courrier en Python
Comment se connecter à AtCoder avec Python et soumettre automatiquement
[Python] Comment faire PCA avec Python
Implémenter la fonction power.prop.test de R en python
Définition du type d'argument de fonction en python
Convertir Markdown en PDF en Python
Comment collecter des images en Python
Formater automatiquement le code Python avec Vim
Comment utiliser SQLite en Python
Ecrire une fonction AWS Lambda en Python
Mesurer le temps d'exécution de la fonction en Python
Dans la commande python, python pointe vers python3.8
Essayez de calculer Trace en Python
Essayez l'accès au registre PLC en Python
Comment utiliser Mysql avec python
Comment envelopper C en Python
Comment utiliser ChemSpider en Python
6 façons d'enchaîner des objets en Python
Comment utiliser PubChem avec Python
Synthèse de fonctions et application en Python
Transmettez des arguments à Task dans discord.py
Inclure "%" dans l'aide argparse pour mourir
Comment utiliser la fonction zip de python
Comment gérer le japonais avec Python
Une alternative à `pause` en Python
[Python] Arguments de fonction * (étoile) et ** (étoile double)
Choses à surveiller lors de l'utilisation d'arguments par défaut en Python
Comment passer des arguments à un script Python dans SPSS Modeler Batch
J'ai écrit une fonction pour charger le script d'extension Git en Python
Essayez de vous connecter automatiquement à Netflix en utilisant python sur votre PC
J'ai essayé d'implémenter PLSA en Python
[Introduction à Python] Comment utiliser la classe en Python?
Essayez de vous connecter à qiita avec Python