Führen Sie die Funktion über die Befehlszeile aus

363

Ich habe diesen Code:

def hello():
    return 'Hi :)'

Wie würde ich dies direkt über die Befehlszeile ausführen?

Steven
quelle
21
Wahrscheinlich meintest du print "Hi :)"statt return 'Hi :)'.
Tamás

Antworten:

567

Mit dem Argument -c (Befehl) (vorausgesetzt, Ihre Datei heißt foo.py):

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

Alternativ, wenn Sie sich nicht für die Verschmutzung von Namespaces interessieren:

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

Und der Mittelweg:

$ python -c 'from foo import hello; print hello()'
Frédéric Hamidi
quelle
32
Ich habe festgestellt, dass Sie unter Windows Shell ein doppeltes Anführungszeichen anstelle eines einfachen Anführungszeichens benötigen. $python -c "import foo;foo.hello()"
Arindam Roychowdhury
6
Was ist, wenn sich die Datei nicht im lokalen Verzeichnis oder auf dem PYTHONPATH befindet?
Konstantin
2
Die zweite ist eine allgemeinere Antwort. Ich habe ein Skript definiert, das mehrere
Kundenfunktionen
1
Aus irgendeinem Grund funktionierte dies bei mir nicht, während das Ersetzen print foo.hello()durch print(foo.hello())tat. Ich habe nicht das Python-Wissen, um zu erklären, warum dies so ist. Wenn also jemand anderes erklären könnte, was los sein kann, wäre das sehr dankbar
Jasper
2
@Aakanksha Danke für die Erklärung, und das macht definitiv Sinn. Scheint es richtig, die Antwort so zu bearbeiten, dass sie die Klammern enthält? Das würde es mit Python 2 und 3 kompatibel machen, wenn ich mich nicht irre. (In solchen Momenten hätte ich gerne einen Bearbeitungsvorschlag machen können.)
Jasper
130

Platzieren Sie es einfach hello()irgendwo unterhalb der Funktion und sie wird ausgeführt, wenn Sie dies tunpython your_file.py

Für eine sauberere Lösung können Sie Folgendes verwenden:

if __name__ == '__main__':
    hello()

Auf diese Weise wird die Funktion nur ausgeführt, wenn Sie die Datei ausführen, nicht beim Importieren der Datei.

Wolph
quelle
3
Und was ist, wenn hello()Argumente verwendet werden, die über die Befehlszeile bereitgestellt werden sollen?
Anonym
2
In diesem Fall können Sie sys.argvan die Methode senden . Oder greifen Sie über die Hallo-Methode darauf zu
Wolph
3
Ein Unterschied zwischen dieser Antwort und der Import-Foo-Lösung besteht darin, dass mit Import-Foo eine beliebige Funktion in Foo aufgerufen werden kann, ohne Foo zu ändern.
Plafratt
Das stimmt, aber ich würde diese Lösung nicht über Testzwecke hinaus empfehlen
Wolph
@Wolph hey mit dieser Struktur, wie führe ich eine separate Funktion (nicht im Inneren enthalten hello()) aus und führe sie über die Kommandozeile aus?
Souvik Ray
66

python -c 'from myfile import hello; hello()'wo myfilemuss durch den Basisnamen Ihres Python-Skripts ersetzt werden. (ZB myfile.pywird myfile).

Wenn hello()es sich jedoch um Ihren "permanenten" Haupteinstiegspunkt in Ihrem Python-Skript handelt, gehen Sie wie folgt vor:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Auf diese Weise können Sie das Skript einfach ausführen, indem Sie python myfile.pyoder ausführen python -m myfile.

Einige Erklärungen hier: __name__ist eine spezielle Python-Variable, die den Namen des Moduls enthält, das gerade ausgeführt wird, außer wenn das Modul über die Befehlszeile gestartet wird "__main__". In diesem Fall wird es .

Tamás
quelle
2
Was ist der Unterschied zwischen python -m foo -c 'foo.bar()'und python -c 'import foo; foo.bar()'? Ich bekomme ein anderes Verhalten, bei dem das Argument -c im ersten Fall ignoriert wird.
Abram
29

Ich habe ein kurzes kleines Python-Skript geschrieben, das über eine Bash-Befehlszeile aufgerufen werden kann. Es enthält den Namen des Moduls, der Klasse und der Methode, die Sie aufrufen möchten, sowie die Parameter, die Sie übergeben möchten. Ich nenne es PyRun und habe die Erweiterung .py weggelassen und es mit chmod + x PyRun ausführbar gemacht, so dass ich es einfach schnell wie folgt aufrufen kann:

./PyRun PyTest.ClassName.Method1 Param1

Speichern Sie dies in einer Datei namens 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)

Hier ist ein Beispielmodul, um zu zeigen, wie es funktioniert. Dies wird in einer Datei namens PyTest.py gespeichert:

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

Versuchen Sie, diese Beispiele auszuführen:

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

Beachten Sie das letzte Beispiel für das Überschreiben der Klammern, um ein Tupel als einzigen Parameter an die zweite Methode zu übergeben.

Wenn Sie zu wenige Parameter für die Anforderungen der Methode übergeben, wird eine Fehlermeldung angezeigt. Wenn Sie zu viele bestehen, werden die Extras ignoriert. Das Modul muss sich im aktuellen Arbeitsordner befinden. PyRun kann sich an einer beliebigen Stelle in Ihrem Pfad befinden.

Joseph Gagliardo
quelle
2
Es ist schön, aber es ist keine wirkliche Antwort auf die Frage.
Francis Colas
14
Ich bin anderer Ansicht; es ist genau die Frage. Er fragte, wie man eine Funktion aus einer Datei ausführt und genau das tut dies.
Joseph Gagliardo
Können Sie erklären, was das bisschen an cmd_folder macht?
RyanDay
26

Fügen Sie dieses Snippet am Ende Ihres Skripts hinzu

def myfunction():
    ...


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

Sie können Ihre Funktion jetzt durch Ausführen aufrufen

python myscript.py myfunction

Dies funktioniert, weil Sie das Befehlszeilenargument (eine Zeichenfolge des Funktionsnamens) an localsein Wörterbuch mit einer aktuellen lokalen Symboltabelle übergeben. Durch die Klammern am Ende wird die Funktion aufgerufen.

Update: Wenn die Funktion einen Parameter über die Befehlszeile akzeptieren soll, können Sie Folgendes übergeben sys.argv[2]:

def myfunction(mystring):
    print mystring


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

Auf diese Weise wird das Ausführen python myscript.py myfunction "hello"ausgegeben hello.

Noam Hacker
quelle
Kann diese Methode einen Parameter für die Funktion akzeptieren? Wiemyfunction(12)
Major Major
@MajorMajor Ich habe die Antwort aktualisiert, um einzuschließen, wie dies zu tun ist
Noam Hacker
Ist dies eine Gefahr für die Live-Produktion? Möchte es als Unit-Test machen.
Ardhi
9

Machen wir es uns etwas leichter und verwenden einfach ein Modul ...

Versuchen: pip install compago

Dann schreibe:

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

Dann verwenden Sie wie folgt:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Hinweis: In Python 3 gibt es derzeit einen Fehler , der jedoch mit Python 2 hervorragend funktioniert.

Bearbeiten: Eine noch bessere Option ist meiner Meinung nach das Modul Feuer von Google, das es einfach macht, auch Funktionsargumente zu übergeben. Es ist installiert mit pip install fire. Von ihrem GitHub:

Hier ist ein einfaches Beispiel.

import fire

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

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

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

Anschließend können Sie über die Befehlszeile Folgendes ausführen:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30
Charles Clayton
quelle
+1. Fire hat sogar die Möglichkeit, eine Funktion aufzurufen, ohne das Skript zu ändern : python -m fire file_name method_name. Es hat auch einen eingebauten Argparser.
user3265569
6

Interessanterweise können Sie Eingaben in den Python-Interpreter wie folgt weiterleiten, wenn das Ziel darin bestand, auf der Befehlszeilenkonsole zu drucken oder eine andere winzige Python-Operation auszuführen:

echo print("hi:)") | python

sowie Pipe-Dateien ..

python < foo.py

* Beachten Sie, dass die Erweiterung nicht .py sein muss, damit die zweite funktioniert. ** Beachten Sie auch, dass Sie für Bash möglicherweise die Zeichen maskieren müssen

echo print\(\"hi:\)\"\) | python
Torie J.
quelle
In Anbetracht des Beispiels foo.py mit hello () kann man es mit der obigen Idee verwenden. echo import foo;foo.hello() | python
Arindam Roychowdhury
Gibt es eine Möglichkeit, Befehlszeilenargumente mit dieser Methode zu übergeben?
sparkonhdfs
1
FWIW, das folgende ist etwas sauberer für das dritte Beispiel:echo 'print("hi:)")' | python
user3166580
5

Wenn Sie das Runp-Paket installieren, müssen Sie Folgendes ausführen pip install runp:

runp myfile.py hello

Sie finden das Repository unter: https://github.com/vascop/runp

vascop
quelle
1
Projekt ist nicht kompatibel mit Python 3.
dim8
4

Ich musste verschiedene Python-Dienstprogramme (Bereich, Zeichenfolge usw.) in der Befehlszeile verwenden und hatte das Tool pyfunc speziell dafür geschrieben. Sie können es verwenden, um Ihre Benutzererfahrung bei der Befehlszeile zu verbessern:

 $ 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
quelle
1

Es ist immer eine Option, Python in der Befehlszeile mit dem Befehl Python einzugeben

Importieren Sie dann Ihre Datei, also importieren Sie example_file

Führen Sie dann den Befehl mit example_file.hello () aus.

Dies vermeidet die seltsame .pyc-Kopierfunktion, die jedes Mal auftritt, wenn Sie python -c usw. ausführen.

Möglicherweise nicht so praktisch wie ein einzelner Befehl, aber eine gute schnelle Lösung, um eine Datei über die Befehlszeile zu schreiben, und ermöglicht es Ihnen, Python zum Aufrufen und Ausführen Ihrer Datei zu verwenden.

user2495144
quelle
1

So etwas wie das: 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

Dies funktioniert in Bash.

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

Unten finden Sie die Datei Odd_Even_function.py mit der Definition der Funktion.

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

Um das gleiche von der Eingabeaufforderung unten aufzurufen, sind die Optionen für mich gearbeitet.

Optionen 1 Vollständiger Pfad der exe \ python.exe -c "Odd_Even_function importieren; Odd_Even_function.OE (100)"

Option 2 Vollständiger Pfad der exe \ python.exe -c "aus Odd_Even_function import OE; OE (100)"

Vielen Dank.

moxit mehta
quelle
0

Diese Funktion kann nicht über die Befehlszeile ausgeführt werden, da sie einen Wert zurückgibt, der unbehandelt bleibt. Sie können die Rücksendung entfernen und stattdessen print verwenden

Shubham
quelle
-2

Verwenden Sie das Python-C- Tool ( pip install python-c ) und schreiben Sie dann einfach:

$ python-c foo 'hello()'

oder falls in Ihren Python-Dateien keine Funktionsnamenkonflikte auftreten:

$ python-c 'hello()'
schwache Monde
quelle
-2

Zuerst müssen Sie die Funktion aufrufen, wie sie Ihnen mitgeteilt wurde, oder die Funktion zeigt nichts in der Ausgabe an. Speichern Sie anschließend die Datei und kopieren Sie den Pfad der Datei, indem Sie mit der rechten Maustaste in den Ordner der Datei klicken und dann auf "Datei kopieren" klicken Gehen Sie zum Terminal und schreiben Sie: - cd "den Pfad der Datei" - Python "Name der Datei zum Beispiel (main.py)" danach wird die Ausgabe Ihres Codes angezeigt.

ShahadM
quelle
-4

Erleichtern Sie sich das Leben und installieren Sie Spyder. Öffnen Sie Ihre Datei und führen Sie sie aus (klicken Sie auf den grünen Pfeil). Anschließend wird Ihre hello()Methode definiert und der IPython-Konsole bekannt, sodass Sie sie von der Konsole aus aufrufen können.

Ivana
quelle