Ejecutar la función desde la línea de comando


363

Tengo este código:

def hello():
    return 'Hi :)'

¿Cómo ejecutaría esto directamente desde la línea de comando?


21
Probablemente quisiste decir en print "Hi :)"lugar de return 'Hi :)'.
Tamás

Respuestas:


567

Con el argumento -c (comando) (suponiendo que se nombre su archivo foo.py):

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

Alternativamente, si no le importa la contaminación del espacio de nombres:

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

Y el término medio:

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

32
Noté que en el shell de Windows, necesita una comilla doble en lugar de una simple. $python -c "import foo;foo.hello()"
Arindam Roychowdhury

66
¿Qué pasa si el archivo no está en el directorio local o en el PYTHONPATH?
Konstantin

2
La segunda es una respuesta más general. Tengo un script que define varias funciones del cliente, y solo llamo a una según mis necesidades
xappppp

1
Por alguna razón, esto no funcionó para mí, mientras reemplaza print foo.hello()con print(foo.hello())lo hizo. No tengo el conocimiento de Python para explicar por qué esto es así, así que si alguien más pudiera explicar lo que está sucediendo, eso sería muy apreciado
Jasper

2
@Aakanksha Gracias por la explicación, y eso definitivamente tiene sentido. ¿Parece correcto editar la respuesta para incluir los paréntesis? Eso lo haría compatible con python 2 y 3 si no me equivoco. (En momentos como este, me hubiera gustado poder hacer una sugerencia de edición.)
Jasper

130

Simplemente coloque en hello()algún lugar debajo de la función y se ejecutará cuando lo hagapython your_file.py

Para una solución más ordenada puede usar esto:

if __name__ == '__main__':
    hello()

De esa forma, la función solo se ejecutará si ejecuta el archivo, no cuando importe el archivo.


3
¿Y qué hello()pasa si toma argumentos que deberían ser proporcionados por la línea de comando?
Anónimo

2
En ese caso, puede enviar sys.argval método. O acceda desde el método hello
Wolph

3
Una diferencia entre esta respuesta y la solución import foo es que import foo permite llamar a una función arbitraria en foo sin modificar foo.
plafratt

Eso es cierto, pero no recomendaría esa solución más allá de los propósitos de la prueba
Wolph el

@Wolph Hola, con esta estructura, ¿cómo ejecuto una función separada (no incluida dentro hello()) y la ejecuto desde la línea de comandos?
Souvik Ray

66

python -c 'from myfile import hello; hello()'donde myfiledebe ser reemplazado con el nombre base de su script Python. (Por ejemplo, se myfile.pyconvierte myfile).

Sin embargo, si hello()es su punto de entrada principal "permanente" en su secuencia de comandos de Python, la forma habitual de hacerlo es la siguiente:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Esto le permite ejecutar el script simplemente ejecutando python myfile.pyo python -m myfile.

Alguna explicación aquí: __name__es una variable especial de Python que contiene el nombre del módulo que se está ejecutando actualmente, excepto cuando el módulo se inicia desde la línea de comandos, en cuyo caso se convierte "__main__".


2
¿Cuál es la diferencia entre python -m foo -c 'foo.bar()'y python -c 'import foo; foo.bar()'? Obtengo un comportamiento diferente donde parece que el argumento -c se ignora en el primer caso.
Abram

29

Escribí un pequeño script Python rápido que se puede llamar desde una línea de comando bash. Toma el nombre del módulo, clase y método al que desea llamar y los parámetros que desea pasar. Lo llamé PyRun y ​​dejé la extensión .py y lo hice ejecutable con chmod + x PyRun para que pueda llamarlo rápidamente de la siguiente manera:

./PyRun PyTest.ClassName.Method1 Param1

Guarda esto en un archivo llamado 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)

Aquí hay un módulo de muestra para mostrar cómo funciona. Esto se guarda en un archivo llamado 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")

Intente ejecutar estos ejemplos:

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

Tenga en cuenta el último ejemplo de escapar de los paréntesis para pasar una tupla como el único parámetro para el segundo método.

Si pasa muy pocos parámetros para lo que necesita el método, obtendrá un error. Si pasa demasiados, ignora los extras. El módulo debe estar en la carpeta de trabajo actual, poner PyRun puede estar en cualquier parte de su ruta.


2
Es agradable, pero en realidad no es una respuesta a la pregunta.
Francis Colas

14
Siento disentir; Es exactamente la pregunta. Preguntó cómo ejecuta una función desde un archivo y eso es exactamente lo que hace.
Joseph Gagliardo

¿Puedes explicar qué está haciendo el bit sobre cmd_folder?
RyanDay

26

agregue este fragmento al final de su secuencia de comandos

def myfunction():
    ...


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

Ahora puede llamar a su función ejecutando

python myscript.py myfunction

Esto funciona porque está pasando el argumento de la línea de comando (una cadena del nombre de la función) en localsun diccionario con una tabla de símbolos local actual. Las paréntesis al final harán que se llame a la función.

actualización: si desea que la función acepte un parámetro de la línea de comando, puede pasar de sys.argv[2]esta manera:

def myfunction(mystring):
    print mystring


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

De esta manera, se ejecutará la python myscript.py myfunction "hello"salida hello.


¿Es posible que este método acepte un parámetro para la función? Tales comomyfunction(12)
Mayor Mayor

@MajorMajor He actualizado la respuesta para incluir cómo hacer esto
Noam Hacker

¿Es esto un peligro hacer esto en la producción en vivo? Como querer hacerlo como una prueba unitaria.
Ardhi

9

Hagamos esto un poco más fácil para nosotros y simplemente usemos un módulo ...

Tratar: pip install compago

Luego escribir:

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

Luego use así:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Nota: Hay un error en Python 3 en este momento, pero funciona muy bien con Python 2.

Editar: una opción aún mejor, en mi opinión, es el módulo de disparo de Google que facilita también pasar argumentos de función. Se instala con pip install fire. De su GitHub:

Aquí hay un ejemplo simple.

import fire

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

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

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

Luego, desde la línea de comandos, puede ejecutar:

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

+1. Fuego, incluso tiene una forma de llamar a una función sin cambiar la secuencia de comandos: python -m fire file_name method_name. También tiene un argparser incorporado.
user3265569

6

Curiosamente, si el objetivo era imprimir en la consola de línea de comandos o realizar alguna otra operación de Python minuciosa, puede canalizar la entrada al intérprete de Python de la siguiente manera:

echo print("hi:)") | python

así como archivos de tubería ...

python < foo.py

* Tenga en cuenta que la extensión no tiene que ser .py para que el segundo funcione. ** También tenga en cuenta que para bash puede que tenga que escapar de los personajes

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

Considerando el ejemplo de foo.py con hello (), así es como se puede usar con la idea anterior. echo import foo;foo.hello() | python
Arindam Roychowdhury

¿Hay alguna forma de pasar argumentos de línea de comandos con este método?
sparkonhdfs

1
FWIW, el siguiente es un poco más limpio para el tercer ejemplo:echo 'print("hi:)")' | python
user3166580


4

Tenía el requisito de usar varias utilidades de python (rango, cadena, etc.) en la línea de comando y había escrito la herramienta pyfunc específicamente para eso. Puede usarlo para enriquecer su experiencia de uso de la línea de comandos:

 $ 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

Siempre es una opción ingresar python en la línea de comando con el comando python

luego importe su archivo para importar ejemplo_archivo

luego ejecute el comando con ejemplo_archivo.hello ()

Esto evita la extraña función de copia .pyc que surge cada vez que ejecuta python -c, etc.

Tal vez no sea tan conveniente como un solo comando, pero es una buena solución rápida para enviar un mensaje de texto a un archivo desde la línea de comandos, y le permite usar python para llamar y ejecutar su archivo.


1

Algo como esto: 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

Esto funciona en bash.

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

1

A continuación se muestra el archivo Odd_Even_function.py que tiene la definición de la función.

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

Ahora, para llamar lo mismo desde el símbolo del sistema a continuación, las opciones me funcionaron.

Opciones 1 Ruta completa de exe \ python.exe -c "import Odd_Even_function; Odd_Even_function.OE (100)"

Opción 2 Ruta completa de exe \ python.exe -c "desde Odd_Even_function import OE; OE (100)"

Gracias.


0

Esta función no se puede ejecutar desde la línea de comando, ya que devuelve un valor que quedará sin control. Puede eliminar la devolución y utilizar imprimir en su lugar


-2

Use la herramienta python-c ( pip install python-c ) y luego simplemente escriba:

$ python-c foo 'hello()'

o en caso de que no haya conflictos de nombres de funciones en sus archivos de Python:

$ python-c 'hello()'

-2

Primero debe llamar a la función como le dijeron o la función no mostrará nada en la salida, luego guarde el archivo y copie la ruta del archivo haciendo clic derecho en la carpeta del archivo y haga clic en "copiar archivo" vaya a la terminal y escriba: - cd "la ruta del archivo" - nombre de python "del archivo, por ejemplo (main.py)" después de eso mostrará la salida de su código.


-4

Haz tu vida más fácil, instala Spyder. Abra su archivo y ejecútelo (haga clic en la flecha verde). Posteriormente, su hello()método está definido y es conocido por la consola IPython, por lo que puede llamarlo desde la consola.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.