Exécuter la fonction à partir de la ligne de commande

363

J'ai ce code:

def hello():
    return 'Hi :)'

Comment pourrais-je l'exécuter directement à partir de la ligne de commande?

Steven
la source
21
Vous vouliez probablement dire print "Hi :)"au lieu de return 'Hi :)'.
Tamás

Réponses:

567

Avec l' argument -c (commande) (en supposant que votre fichier est nommé foo.py):

$ python -c 'import foo; print foo.hello()'

Alternativement, si vous ne vous souciez pas de la pollution de l'espace de noms:

$ python -c 'from foo import *; print hello()'

Et le juste milieu:

$ python -c 'from foo import hello; print hello()'
Frédéric Hamidi
la source
32
J'ai remarqué que sur le shell Windows, vous avez besoin d'un guillemet double au lieu d'un simple. $python -c "import foo;foo.hello()"
Arindam Roychowdhury
6
Que faire si le fichier n'est pas dans le répertoire local ou sur le PYTHONPATH?
Konstantin
2
La seconde est une réponse plus générale. J'ai un script défini plusieurs fonctions client, et n'appelle qu'une seule en fonction de mes besoins
xappppp
1
Pour une raison quelconque, cela n'a pas fonctionné pour moi, tout en remplaçant print foo.hello()par l'a print(foo.hello())fait. Je n'ai pas les connaissances en python pour expliquer pourquoi, donc si quelqu'un d'autre pouvait expliquer ce qui pouvait se passer, ce serait grandement apprécié
Jasper
2
@Aakanksha Merci pour l'explication, et cela a vraiment du sens. Semble-t-il correct de modifier la réponse pour inclure les parenthèses? Cela le rendrait compatible avec les deux python 2 et 3 si je ne me trompe pas. (À des moments comme celui-ci, j'aurais aimé pouvoir faire une suggestion de modification.)
Jasper
130

Mettez juste hello()quelque part en dessous de la fonction et elle s'exécutera lorsque vous le ferezpython your_file.py

Pour une solution plus nette, vous pouvez utiliser ceci:

if __name__ == '__main__':
    hello()

De cette façon, la fonction ne sera exécutée que si vous exécutez le fichier, pas lorsque vous importez le fichier.

Wolph
la source
3
Et si hello()prend des arguments qui devraient être fournis par la ligne de commande?
Anonyme
2
Dans ce cas, vous pouvez envoyer sys.argvà la méthode. Ou accédez-y à partir de la méthode bonjour
Wolph
3
Une différence entre cette réponse et la solution d'importation foo est que l'importation foo permet d'appeler une fonction arbitraire dans foo sans modifier foo.
plafratt
C'est vrai, mais je ne recommanderais pas cette solution au-delà des fins de test
Wolph
@Wolph hey avec cette structure, comment puis-je exécuter une fonction séparée (non incluse à l'intérieur hello()) et l'exécuter à partir de la ligne de commande?
Souvik Ray
66

python -c 'from myfile import hello; hello()'myfiledoit être remplacé par le nom de base de votre script Python. (Par exemple, myfile.pydevient myfile).

Cependant, si hello()est votre point d'entrée principal "permanent" dans votre script Python, la façon habituelle de le faire est la suivante:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Cela vous permet d'exécuter le script simplement en exécutant python myfile.pyou python -m myfile.

Quelques explications ici: __name__est une variable Python spéciale qui contient le nom du module en cours d'exécution, sauf lorsque le module est démarré à partir de la ligne de commande, auquel cas il le devient "__main__".

Tamás
la source
2
Quelle est la difference entre python -m foo -c 'foo.bar()'et python -c 'import foo; foo.bar()'? J'obtiens un comportement différent où il semble que l'argument -c soit ignoré dans le premier cas.
Abram
29

J'ai écrit un petit script Python rapide qui peut être appelé à partir d'une ligne de commande bash. Il prend le nom du module, de la classe et de la méthode que vous souhaitez appeler et les paramètres que vous souhaitez transmettre. Je l'appelle PyRun et ai laissé l'extension .py et l'ai rendue exécutable avec chmod + x PyRun afin que je puisse l'appeler rapidement comme suit:

./PyRun PyTest.ClassName.Method1 Param1

Enregistrez-le dans un fichier appelé PyRun

#!/usr/bin/env python
#make executable in bash chmod +x PyRun

import sys
import inspect
import importlib
import os

if __name__ == "__main__":
    cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
    if cmd_folder not in sys.path:
        sys.path.insert(0, cmd_folder)

    # get the second argument from the command line      
    methodname = sys.argv[1]

    # split this into module, class and function name
    modulename, classname, funcname = methodname.split(".")

    # get pointers to the objects based on the string names
    themodule = importlib.import_module(modulename)
    theclass = getattr(themodule, classname)
    thefunc = getattr(theclass, funcname)

    # pass all the parameters from the third until the end of 
    # what the function needs & ignore the rest
    args = inspect.getargspec(thefunc)
    z = len(args[0]) + 2
    params=sys.argv[2:z]
    thefunc(*params)

Voici un exemple de module pour montrer comment cela fonctionne. Ceci est enregistré dans un fichier appelé PyTest.py:

class SomeClass:
 @staticmethod
 def First():
     print "First"

 @staticmethod
 def Second(x):
    print(x)
    # for x1 in x:
    #     print x1

 @staticmethod
 def Third(x, y):
     print x
     print y

class OtherClass:
    @staticmethod
    def Uno():
        print("Uno")

Essayez d'exécuter ces exemples:

./PyRun PyTest.SomeClass.First
./PyRun PyTest.SomeClass.Second Hello
./PyRun PyTest.SomeClass.Third Hello World
./PyRun PyTest.OtherClass.Uno
./PyRun PyTest.SomeClass.Second "Hello"
./PyRun PyTest.SomeClass.Second \(Hello, World\)

Notez le dernier exemple d'échappement des parenthèses pour passer dans un tuple comme seul paramètre à la deuxième méthode.

Si vous passez trop peu de paramètres pour ce dont la méthode a besoin, vous obtenez une erreur. Si vous en passez trop, il ignore les extras. Le module doit être dans le dossier de travail actuel, mis PyRun peut être n'importe où sur votre chemin.

Joseph Gagliardo
la source
2
C'est bien, mais ce n'est pas vraiment une réponse à la question.
Francis Colas
14
Je ne suis pas d'accord; c'est exactement la question. Il a demandé comment exécuter une fonction à partir d'un fichier et c'est exactement ce que cela fait.
Joseph Gagliardo
Pouvez-vous expliquer ce que fait le bit sur cmd_folder?
RyanDay
26

ajoutez cet extrait au bas de votre script

def myfunction():
    ...


if __name__ == '__main__':
    globals()[sys.argv[1]]()

Vous pouvez maintenant appeler votre fonction en exécutant

python myscript.py myfunction

Cela fonctionne parce que vous passez l'argument de ligne de commande (une chaîne du nom de la fonction) dans localsun dictionnaire avec une table de symboles locale actuelle. Les parenthèses à la fin feront appeler la fonction.

mise à jour: si vous souhaitez que la fonction accepte un paramètre de la ligne de commande, vous pouvez passer sys.argv[2]comme ceci:

def myfunction(mystring):
    print mystring


if __name__ == '__main__':
    globals()[sys.argv[1]](sys.argv[2])

De cette façon, l'exécution python myscript.py myfunction "hello"sortira hello.

Noam Hacker
la source
Est-il possible pour cette méthode d'accepter un paramètre pour la fonction? Tels quemyfunction(12)
Major Major
@MajorMajor J'ai mis à jour la réponse pour inclure comment faire cela
Noam Hacker
est-ce un danger de faire cela dans la production en direct? Comme vouloir le faire comme un test unitaire.
Ardhi
9

Rendons cela un peu plus facile pour nous et utilisons simplement un module ...

Essayer: pip install compago

Puis écrire:

import compago
app = compago.Application()

@app.command
def hello():
    print "hi there!"

@app.command
def goodbye():
    print "see ya later."

if __name__ == "__main__":
    app.run()

Ensuite, utilisez comme ceci:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Remarque: Il existe actuellement un bogue dans Python 3, mais fonctionne très bien avec Python 2.

Edit: Une option encore meilleure, à mon avis, est le module fire de Google qui permet également de passer facilement des arguments de fonction. Il est installé avec pip install fire. Depuis leur GitHub:

Voici un exemple simple.

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

Ensuite, à partir de la ligne de commande, vous pouvez exécuter:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30
Charles Clayton
la source
+1. Le feu a même un moyen d'appeler une fonction sans changer le script: python -m fire file_name method_name. Il a également un argparser intégré.
user3265569
6

Chose intéressante, si l'objectif était d'imprimer sur la console de ligne de commande ou d'effectuer une autre opération python minute, vous pouvez diriger l'entrée dans l'interpréteur python comme suit:

echo print("hi:)") | python

ainsi que des fichiers de tuyaux ..

python < foo.py

* Notez que l'extension n'a pas besoin d'être .py pour que la seconde fonctionne. ** Notez également que pour bash, vous devrez peut-être échapper aux personnages

echo print\(\"hi:\)\"\) | python
Torie J
la source
Considérant l'exemple foo.py avec hello (), voici comment on peut l'utiliser avec l'idée ci-dessus. echo import foo;foo.hello() | python
Arindam Roychowdhury
Existe-t-il un moyen de passer des arguments de ligne de commande avec cette méthode?
sparkonhdfs
1
FWIW, ce qui suit est légèrement plus propre pour le troisième exemple:echo 'print("hi:)")' | python
user3166580
5

Si vous installez le package runp avec pip install runpune question de fonctionnement:

runp myfile.py hello

Vous pouvez trouver le référentiel sur: https://github.com/vascop/runp

vascop
la source
1
Le projet n'est pas compatible avec Python 3.
dim8
4

J'avais besoin d'utiliser divers utilitaires python (plage, chaîne, etc.) sur la ligne de commande et j'avais écrit l'outil pyfunc spécifiquement pour cela. Vous pouvez l'utiliser pour enrichir votre expérience d'utilisation de la ligne de commande:

 $ pyfunc -m range -a 1 7 2
 1
 3
 5

 $ pyfunc -m string.upper -a test
 TEST

 $ pyfunc -m string.replace -a 'analyze what' 'what' 'this'
 analyze this
Saurabh Hirani
la source
1

C'est toujours une option pour entrer python sur la ligne de commande avec la commande python

puis importez votre fichier afin d' importer exemple_fichier

puis exécutez la commande avec example_file.hello ()

Cela évite la fonction de copie .pyc bizarre qui apparaît à chaque fois que vous exécutez python -c, etc.

Peut-être pas aussi pratique qu'une commande unique, mais une bonne solution rapide pour envoyer un fichier texte à partir de la ligne de commande, et vous permet d'utiliser python pour appeler et exécuter votre fichier.

user2495144
la source
1

Quelque chose comme ça: call_from_terminal.py

# call_from_terminal.py
# Ex to run from terminal
# ip='"hi"'
# python -c "import call_from_terminal as cft; cft.test_term_fun(${ip})"
# or
# fun_name='call_from_terminal'
# python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
def test_term_fun(ip):
    print ip

Cela fonctionne en bash.

$ ip='"hi"' ; fun_name='call_from_terminal' 
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi
Al Conrad
la source
1

Ci-dessous se trouve le fichier Odd_Even_function.py qui a la définition de la fonction.

def OE(n):
    for a in range(n):
        if a % 2 == 0:
            print(a)
        else:
            print(a, "ODD")

Maintenant, pour appeler la même chose à partir de l'invite de commande ci-dessous, les options fonctionnent pour moi.

Options 1 Chemin complet de l'exe \ python.exe -c "import Odd_Even_function; Odd_Even_function.OE (100)"

Option 2 Chemin complet de l'exe \ python.exe -c "d'Odd_Even_function import OE; OE (100)"

Merci.

moxit mehta
la source
0

Cette fonction ne peut pas être exécutée à partir de la ligne de commande car elle renvoie une valeur qui ne sera pas manipulée. Vous pouvez supprimer le retour et utiliser plutôt print

Shubham
la source
-2

Utilisez l' outil python-c ( pip install python-c ) puis écrivez simplement:

$ python-c foo 'hello()'

ou si vous n'avez aucun conflit de nom de fonction dans vos fichiers python:

$ python-c 'hello()'
faiblesses
la source
-2

Vous devez d'abord appeler la fonction comme ils vous l'ont dit ou la fonction n'affichera rien dans la sortie, après cela enregistrez le fichier et copiez le chemin du fichier par un clic droit sur le dossier du fichier et cliquez sur "copier le fichier" puis allez dans le terminal et écrivez: - cd "le chemin du fichier" - python "nom du fichier par exemple (main.py)" après cela il affichera la sortie de votre code.

ShahadM
la source
-4

Simplifiez-vous la vie, installez Spyder. Ouvrez votre fichier puis exécutez-le (cliquez sur la flèche verte). Ensuite, votre hello()méthode est définie et connue de la console IPython, vous pouvez donc l'appeler à partir de la console.

Ivana
la source