Uruchom funkcję z wiersza poleceń

363

Mam ten kod:

def hello():
    return 'Hi :)'

Jak miałbym to uruchomić bezpośrednio z wiersza poleceń?

Steven
źródło
21
Prawdopodobnie miałeś na myśli print "Hi :)"zamiast return 'Hi :)'.
Tamás

Odpowiedzi:

566

Za pomocą argumentu -c (polecenie) (zakładając, że plik ma nazwę foo.py):

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

Alternatywnie, jeśli nie obchodzi Cię zanieczyszczenie przestrzeni nazw:

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

I środek:

$ python -c 'from foo import hello; print hello()'
Frédéric Hamidi
źródło
32
Zauważyłem, że w powłoce systemu Windows potrzebujesz podwójnego cudzysłowu zamiast pojedynczego. $python -c "import foo;foo.hello()"
Arindam Roychowdhury
6
Co jeśli plik nie znajduje się w katalogu lokalnym lub w ścieżce PYTHONPATH?
Konstantin
2
Druga jest bardziej ogólną odpowiedzią. Mam zdefiniowany w skrypcie wiele funkcji klienta i
wywołuję
1
Z jakiegoś powodu to nie działało dla mnie, podczas gdy zastępowanie print foo.hello()przez print(foo.hello())nie. Nie mam wiedzy pythonowej, aby wyjaśnić, dlaczego tak jest, więc jeśli ktoś inny mógłby wyjaśnić, co się dzieje, byłoby to bardzo mile widziane
Jasper
2
@Aakanksha Dzięki za wyjaśnienie, a to na pewno ma sens. Czy edytowanie odpowiedzi w nawiasach wydaje się słuszne? Dzięki temu byłby kompatybilny zarówno z Pythonem 2, jak i 3, jeśli się nie mylę. (W takich chwilach chciałbym móc zaproponować edycję.)
Jasper
130

Po prostu umieść hello()gdzieś poniżej funkcji, a wykona się, gdy to zrobiszpython your_file.py

Aby uzyskać fajniejsze rozwiązanie, możesz użyć tego:

if __name__ == '__main__':
    hello()

W ten sposób funkcja zostanie uruchomiona tylko po uruchomieniu pliku, a nie po zaimportowaniu pliku.

Wolph
źródło
3
A co, jeśli hello()pobierze argumenty, które powinny być dostarczone z wiersza poleceń?
Anonimowy
2
W takim przypadku możesz wysłać sys.argvdo metody. Lub skorzystaj z metody hello
Wolph
3
Jedną z różnic między tą odpowiedzią a rozwiązaniem foo importu jest to, że import foo pozwala na wywołanie dowolnej funkcji w foo bez modyfikowania foo.
plafratt
To prawda, ale nie poleciłbym tego rozwiązania poza celami testowymi
Wolph
@Wolph hej z tą strukturą, jak wykonać oddzielną funkcję (nie zawartą w środku hello()) i uruchomić ją z wiersza poleceń?
Souvik Ray
66

python -c 'from myfile import hello; hello()'gdzie myfilenależy zastąpić bazame skryptu Python. (Np. myfile.pyStaje się myfile).

Jeśli jednak hello()jest to „stały” główny punkt wejścia w skrypcie w języku Python, zwykły sposób na zrobienie tego jest następujący:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Pozwala to na wykonanie skryptu po prostu przez uruchomienie python myfile.pylub python -m myfile.

Oto niektóre wyjaśnienia: __name__jest to specjalna zmienna Pythona, która przechowuje nazwę aktualnie wykonywanego modułu, z wyjątkiem sytuacji, gdy moduł jest uruchamiany z wiersza poleceń, w którym to przypadku staje się "__main__".

Tamás
źródło
2
Jaka jest różnica między python -m foo -c 'foo.bar()'i python -c 'import foo; foo.bar()'? Dostaję inne zachowanie, w którym wydaje się, że argument -c jest ignorowany w pierwszym przypadku.
Abram,
29

Napisałem szybki skrypt w języku Python, który można wywołać z linii poleceń bash. Pobiera nazwę modułu, klasy i metody, którą chcesz wywołać, oraz parametry, które chcesz przekazać. Nazywam go PyRun, zrezygnowałem z rozszerzenia .py i sprawiłem, że jest wykonywalny za pomocą chmod + x PyRun, dzięki czemu mogę po prostu wywołać go szybko w następujący sposób:

./PyRun PyTest.ClassName.Method1 Param1

Zapisz to w pliku o nazwie 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)

Oto przykładowy moduł pokazujący, jak to działa. Jest to zapisywane w pliku o nazwie 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")

Spróbuj uruchomić następujące przykłady:

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

Zwróć uwagę na ostatni przykład ucieczki z nawiasów, aby przekazać krotkę jako jedyny parametr do drugiej metody.

Jeśli przekażesz za mało parametrów dla potrzebnej metody, pojawi się błąd. Jeśli zdasz zbyt wiele, ignoruje dodatki. Moduł musi znajdować się w bieżącym folderze roboczym, umieścić PyRun może być w dowolnym miejscu na ścieżce.

Joseph Gagliardo
źródło
2
To miłe, ale tak naprawdę nie jest to odpowiedź na pytanie.
Francis Colas,
14
Pozwolę sobie być innego zdania; to jest dokładnie pytanie. Zapytał, jak uruchomić funkcję z pliku i tak właśnie działa.
Joseph Gagliardo
Czy możesz wyjaśnić, co robi kawałek cmd_folder?
RyanDay
26

dodaj ten fragment kodu na dole skryptu

def myfunction():
    ...


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

Możesz teraz wywołać swoją funkcję, uruchamiając

python myscript.py myfunction

Działa to, ponieważ przekazujesz argument wiersza poleceń (ciąg nazwy funkcji) do locals słownika z bieżącą lokalną tablicą symboli. Nawiasy na końcu spowodują wywołanie funkcji.

aktualizacja: jeśli chcesz, aby funkcja akceptowała parametr z wiersza poleceń, możesz przekazać w sys.argv[2]następujący sposób:

def myfunction(mystring):
    print mystring


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

W ten sposób uruchomione python myscript.py myfunction "hello"zostanie wyjście hello.

Noam Hacker
źródło
Czy ta metoda może zaakceptować parametr dla funkcji? Takich jakmyfunction(12)
Major Major
@MajorMajor Zaktualizowałem odpowiedź, aby uwzględnić, jak to zrobić
Noam Hacker
czy jest to niebezpieczne w przypadku produkcji na żywo? Jak chcesz zrobić to jako test jednostkowy.
Ardhi
9

Ułatwmy to sobie i po prostu skorzystaj z modułu ...

Próbować: pip install compago

Następnie napisz:

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

Następnie użyj tak:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Uwaga: w tej chwili jest błąd w Pythonie 3, ale działa świetnie z Pythonem 2.

Edycja: Jeszcze lepszą opcją, moim zdaniem, jest moduł uruchamiany przez Google, który ułatwia przekazywanie argumentów funkcji. Jest instalowany z pip install fire. Z ich GitHub:

Oto prosty przykład.

import fire

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

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

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

Następnie z wiersza poleceń możesz uruchomić:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30
Charles Clayton
źródło
+1. Ogień ma nawet drogę do wywołania funkcji bez zmiany skryptu: python -m fire file_name method_name. Ma również wbudowany argparser.
user3265569
6

Co ciekawe, jeśli celem było wydrukowanie na konsoli wiersza poleceń lub wykonanie innej drobnej operacji w języku Python, możesz przesłać dane wejściowe do interpretera języka Python w następujący sposób:

echo print("hi:)") | python

a także pliki potoków ..

python < foo.py

* Pamiętaj, że rozszerzenie nie musi być .py, aby sekunda zadziałała. ** Pamiętaj też, że w przypadku bashu może być konieczne ucieczka postaci

echo print\(\"hi:\)\"\) | python
Torie J.
źródło
Biorąc pod uwagę przykład foo.py z hello (), można go używać z powyższym pomysłem. echo import foo;foo.hello() | python
Arindam Roychowdhury
Czy istnieje jakikolwiek sposób przekazania argumentów wiersza polecenia za pomocą tej metody?
sparkonhdfs
1
FWIW, trzeci przykład jest nieco czystszy:echo 'print("hi:)")' | python
user3166580,
5

Jeśli zainstalujesz pakiet runp, pip install runpto kwestia uruchomienia:

runp myfile.py hello

Repozytorium można znaleźć na stronie : https://github.com/vascop/runp

vascop
źródło
1
Projekt nie jest kompatybilny z Python 3.
dim8
4

Miałem wymóg używania różnych narzędzi Pythona (zakres, ciąg itp.) W wierszu poleceń i specjalnie dla tego napisałem narzędzie pyfunc . Możesz go użyć, aby wzbogacić korzystanie z wiersza poleceń:

 $ 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
źródło
1

Zawsze można wpisać python w wierszu poleceń za pomocą polecenia python

następnie zaimportuj plik, więc zaimportuj plik_przykładowy

następnie uruchom polecenie za pomocą example_file.hello ()

Pozwala to uniknąć dziwnej funkcji kopiowania .pyc, która pojawia się przy każdym uruchomieniu Pythona -c itp.

Może nie tak wygodne jak pojedyncze polecenie, ale dobra szybka poprawka na tekst pliku z wiersza poleceń i pozwala używać Pythona do wywoływania i wykonywania pliku.

użytkownik2495144
źródło
1

Coś takiego: 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

To działa w trybie bash.

$ ip='"hi"' ; fun_name='call_from_terminal' 
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi
Al Conrad
źródło
1

Poniżej znajduje się plik Odd_Even_function.py, który ma definicję funkcji.

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

Teraz, aby zadzwonić tak samo z wiersza polecenia poniżej, sprawdziłem opcje.

Opcje 1 Pełna ścieżka do pliku exe \ python.exe -c „import Odd_Even_function; Odd_Even_function.OE (100)”

Opcja 2 Pełna ścieżka do pliku exe \ python.exe -c "z funkcji Odd_Even_function import OE; OE (100)"

Dzięki.

moxit mehta
źródło
0

Ta funkcja nie może być uruchomiona z wiersza poleceń, ponieważ zwraca wartość, która nie będzie obsługiwana. Możesz usunąć zwrot i zamiast tego użyć print

Shubham
źródło
-2

Użyj narzędzia python-c ( pip install python-c ), a następnie po prostu napisz:

$ python-c foo 'hello()'

lub w przypadku braku konfliktów nazw funkcji w plikach Pythona:

$ python-c 'hello()'
słaby księżyc
źródło
-2

Najpierw musisz wywołać funkcję, tak jak ci powiedzieli, w przeciwnym razie nic nie wyświetli wyniku, następnie zapisz plik i skopiuj ścieżkę pliku, klikając prawym przyciskiem myszy na folder pliku, a następnie „kopiuj plik”, a następnie przejdź do terminala i napisz: - cd „ścieżka do pliku” - python „nazwa pliku na przykład (main.py)”, po czym wyświetli wyjście twojego kodu.

ShahadM
źródło
-4

Ułatw sobie życie, zainstaluj Spyder. Otwórz plik, a następnie uruchom go (kliknij zieloną strzałkę). Następnie twoja hello()metoda jest zdefiniowana i znana Konsoli IPython, więc możesz wywoływać ją z konsoli.

Ivana
źródło