Esegui la funzione dalla riga di comando


363

Ho questo codice:

def hello():
    return 'Hi :)'

Come eseguirò questo direttamente dalla riga di comando?


21
Probabilmente intendevi print "Hi :)"invece di return 'Hi :)'.
Tamás,

Risposte:


567

Con l' argomento -c (comando) (supponendo che il tuo file sia chiamato foo.py):

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

In alternativa, se non ti interessa l'inquinamento dello spazio dei nomi:

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

E la via di mezzo:

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

32
Ho notato che sulla shell di Windows, hai bisogno di una doppia citazione anziché singola. $python -c "import foo;foo.hello()"
Arindam Roychowdhury,

6
Cosa succede se il file non si trova nella directory locale o su PYTHONPATH?
Konstantin,

2
La seconda è una risposta più generale. Ho uno script definito per più funzioni cliente e ne chiamo solo una a seconda delle mie necessità
xappppp

1
Per qualche ragione, questo non ha funzionato per me, mentre lo ha fatto print foo.hello()con la sostituzione print(foo.hello()). Non ho la conoscenza di Python per spiegare perché, quindi se qualcun altro potesse spiegare cosa può succedere, sarebbe molto apprezzato
Jasper

2
@Aakanksha Grazie per la spiegazione, e questo ha sicuramente senso. Sembra giusto modificare la risposta per includere le parentesi? Ciò lo renderebbe compatibile sia con Python 2 che 3 se non sbaglio. (In momenti come questo, mi sarebbe piaciuto poter dare un suggerimento di modifica.)
Jasper

130

Basta mettere hello()da qualche parte sotto la funzione e verrà eseguita quando lo faipython your_file.py

Per una soluzione più ordinata puoi usare questo:

if __name__ == '__main__':
    hello()

In questo modo la funzione verrà eseguita solo se si esegue il file, non quando si importa il file.


3
E se hello()accetta argomenti che dovrebbero essere forniti dalla riga di comando?
Anonimo il

2
In tal caso è possibile inviare sys.argval metodo. O accedi al metodo hello
Wolph,

3
Una differenza tra questa risposta e la soluzione import foo è che import foo consente di chiamare una funzione arbitraria in foo senza modificare foo.
plafratt,

È vero, ma non consiglierei questa soluzione oltre gli scopi del test
Wolph,

@Wolph hey con questa struttura, come posso eseguire una funzione separata (non inclusa all'interno hello()) ed eseguirla dalla riga di comando?
Souvik Ray,

66

python -c 'from myfile import hello; hello()'dove myfiledeve essere sostituito con il nome di base dello script Python. (Ad esempio, myfile.pydiventa myfile).

Tuttavia, se hello()è il punto di ingresso principale "permanente" nel tuo script Python, il solito modo per farlo è il seguente:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Ciò consente di eseguire lo script semplicemente eseguendo python myfile.pyo python -m myfile.

Qualche spiegazione qui: __name__è una speciale variabile Python che contiene il nome del modulo attualmente in esecuzione, tranne quando il modulo viene avviato dalla riga di comando, nel qual caso diventa "__main__".


2
Qual è la differenza tra python -m foo -c 'foo.bar()'e python -c 'import foo; foo.bar()'? Ricevo comportamenti diversi dove sembra che l'argomento -c sia ignorato nel primo caso.
Abram,

29

Ho scritto un breve script Python richiamabile da una riga di comando bash. Prende il nome del modulo, la classe e il metodo che si desidera chiamare e i parametri che si desidera passare. Lo chiamo PyRun e ho lasciato l'estensione .py e l'ho reso eseguibile con chmod + x PyRun in modo da poterlo chiamare rapidamente come segue:

./PyRun PyTest.ClassName.Method1 Param1

Salvalo in un file chiamato 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)

Ecco un modulo di esempio per mostrare come funziona. Questo viene salvato in un file chiamato 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")

Prova a eseguire questi esempi:

./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\)

Nota l'ultimo esempio di escape delle parentesi per passare in una tupla come unico parametro al secondo metodo.

Se passi troppi pochi parametri per ciò di cui ha bisogno il metodo, ricevi un errore. Se ne passi troppi, ignora gli extra. Il modulo deve trovarsi nella cartella di lavoro corrente, mettere PyRun può trovarsi ovunque nel percorso.


2
È carino, ma non è proprio una risposta alla domanda.
Francis Colas,

14
Mi permetto di dissentire; è esattamente la domanda. Ha chiesto come si esegue una funzione da un file ed è esattamente quello che fa.
Joseph Gagliardo,

Puoi spiegare cosa sta facendo il bit di cmd_folder?
Ryan

26

aggiungi questo frammento in fondo allo script

def myfunction():
    ...


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

Ora puoi chiamare la tua funzione eseguendo

python myscript.py myfunction

Questo funziona perché stai passando l'argomento della riga di comando (una stringa del nome della funzione) in localsun dizionario con una tabella di simboli locale corrente. Le parentesi alla fine faranno chiamare la funzione.

aggiornamento: se si desidera che la funzione accetti un parametro dalla riga di comando, è possibile passare in sys.argv[2]questo modo:

def myfunction(mystring):
    print mystring


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

In questo modo, l'esecuzione python myscript.py myfunction "hello"funzionerà hello.


È possibile per questo metodo accettare un parametro per la funzione? Come ad esempiomyfunction(12)
Maggiore Maggiore

@MajorMajor Ho aggiornato la risposta per includere come fare
Noam Hacker

è un pericolo farlo nella produzione live? Come voler farlo come un test unitario.
Ardhi,

9

Rendiamolo un po 'più semplice per noi stessi e basta usare un modulo ...

Provare: pip install compago

Allora scrivi:

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

Quindi utilizzare in questo modo:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Nota: al momento c'è un bug in Python 3, ma funziona benissimo con Python 2.

Modifica: un'opzione ancora migliore, secondo me è il modulo fire di Google che rende facile anche passare argomenti di funzione. È installato con pip install fire. Dal loro GitHub:

Ecco un semplice esempio.

import fire

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

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

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

Quindi, dalla riga di comando, puoi eseguire:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

+1. Il fuoco ha anche un modo per chiamare una funzione senza modificare lo script: python -m fire file_name method_name. Ha anche un argparser incorporato.
user3265569,

6

È interessante notare che, se l'obiettivo era stampare sulla console della riga di comando o eseguire qualche altra operazione Python minuto, è possibile reindirizzare l'input nell'interprete Python in questo modo:

echo print("hi:)") | python

così come i file di pipe ..

python < foo.py

* Nota che l'estensione non deve essere .py affinché il secondo funzioni. ** Si noti inoltre che per bash potrebbe essere necessario sfuggire ai personaggi

echo print\(\"hi:\)\"\) | python

Considerando l'esempio foo.py con hello (), ecco come si può usare con l'idea di cui sopra. echo import foo;foo.hello() | python
Arindam Roychowdhury

Esiste un modo per passare argomenti della riga di comando con questo metodo?
sparkonhdfs

1
FWIW, quanto segue è leggermente più pulito per il terzo esempio:echo 'print("hi:)")' | python
user3166580


4

Avevo l'obbligo di utilizzare varie utility Python (range, string, ecc.) Sulla riga di comando e avevo scritto lo strumento pyfunc appositamente per quello. Puoi usarlo per arricchire la tua esperienza di utilizzo da riga di comando:

 $ 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

1

È sempre un'opzione per inserire python sulla riga di comando con il comando python

quindi importa il tuo file in modo da importare example_file

quindi esegui il comando con example_file.hello ()

Questo evita la strana funzione di copia .pyc che compare ogni volta che esegui python -c ecc.

Forse non è conveniente come un singolo comando, ma una buona soluzione rapida per inviare un file di testo dalla riga di comando e ti consente di usare Python per chiamare ed eseguire il tuo file.


1

Qualcosa del genere: 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

Questo funziona in bash.

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

1

Di seguito è riportato il file Odd_Even_function.py che ha la definizione della funzione.

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

Ora per chiamare lo stesso dal prompt dei comandi di seguito sono le opzioni lavorate per me.

Opzioni 1 Percorso completo di exe \ python.exe -c "import Odd_Even_function; Odd_Even_function.OE (100)"

Opzione 2 Percorso completo di exe \ python.exe -c "da Odd_Even_function import OE; OE (100)"

Grazie.


0

Questa funzione non può essere eseguita dalla riga di comando poiché restituisce un valore che non verrà gestito. Puoi rimuovere il reso e usare invece print


-2

Usa lo strumento python-c ( installa pip python-c ) e poi scrivi semplicemente:

$ python-c foo 'hello()'

o nel caso in cui non ci siano conflitti tra i nomi delle funzioni nei file Python:

$ python-c 'hello()'

-2

Per prima cosa devi chiamare la funzione come ti hanno detto o la founction non mostrerà nulla nell'output, dopodiché salva il file e copia il percorso del file facendo clic con il pulsante destro del mouse sulla cartella del file e fai clic su "copia file", quindi vai al terminale e scrivi: - cd "il percorso del file" - python "nome del file per esempio (main.py)" dopo di che visualizzerà l'output del tuo codice.


-4

Semplifica la vita, installa Spyder. Apri il tuo file quindi eseguilo (fai clic sulla freccia verde). Successivamente il hello()metodo viene definito e noto alla console IPython, quindi è possibile chiamarlo dalla console.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.