Запустити функцію з командного рядка


363

У мене є цей код:

def hello():
    return 'Hi :)'

Як би я запустив це безпосередньо з командного рядка?


21
Напевно, ви мали на увазі print "Hi :)"замість цього return 'Hi :)'.
Тамас

Відповіді:


566

З аргументом -c (command) (якщо присвоїти ім'я файлу foo.py):

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

Крім того, якщо вам не байдуже забруднення простору імен:

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

І середина:

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

32
Я зазначив, що для оболонки Windows вам потрібна подвійна цитата, а не одна. $python -c "import foo;foo.hello()"
Arindam Roychowdhury

6
Що робити, якщо файл не знаходиться в локальному каталозі або в PYTHONPATH?
Костянтин

2
Другий - більш загальна відповідь. У мене є сценарій, визначений декількома функціями замовника, і дзвоню лише один, залежно від моєї потреби
xappppp

1
Чомусь це не спрацювало для мене, тоді як замінила print foo.hello()на " print(foo.hello()). У мене немає знань пітона, щоб пояснити, чому це так, тож якщо хтось інший міг би пояснити, що може йти, це було б дуже вдячно
Джаспер

2
@Aakanksha Дякую за пояснення, і це, безумовно, має сенс. Чи здається правильним редагувати відповідь, щоб включити дужки? Це зробило б його сумісним і з python 2, і з 3, якщо я не помиляюся. (У такі моменти, як я хотів би, щоб я міг зробити пропозицію щодо редагування.)
Джаспер,

130

Просто поставте hello()десь нижче функції, і вона буде виконуватися, коли ви це зробитеpython your_file.py

Для більш охайного рішення ви можете скористатися цим:

if __name__ == '__main__':
    hello()

Таким чином функція буде виконуватися лише в тому випадку, якщо ви запускаєте файл, а не при імпорті файлу.


3
А що робити, якщо hello()приймаються аргументи, які повинні подаватися в командному рядку?
Анонім

2
У такому випадку ви можете надіслати sys.argvметод. Або отримати доступ до нього з привітного методу
Вольф

3
Одна відмінність цього відповіді від рішення імпорту foo полягає в тому, що імпорт foo дозволяє викликати довільну функцію в foo, не змінюючи foo.
plafratt

Це правда, але я б не рекомендував це рішення поза тестовими цілями
Вольф

@Wolph hey з цією структурою, як я можу виконати окрему функцію (не включена всередину hello()) і запустити її з командного рядка?
Сувік Рей

66

python -c 'from myfile import hello; hello()'де myfileпотрібно замінити базове ім'я вашого сценарію Python. (Наприклад, myfile.pyстає myfile).

Однак якщо hello()ваша «постійна» головна точка входу в ваш сценарій Python, то звичайний спосіб це зробити наступним чином:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Це дозволяє виконати сценарій, просто запустивши python myfile.pyабо python -m myfile.

Деякі пояснення тут: __name__це спеціальна змінна Python, яка містить ім'я модуля, який зараз виконується, за винятком випадків, коли модуль запускається з командного рядка, і в такому випадку він стає "__main__".


2
У чому різниця між python -m foo -c 'foo.bar()'і python -c 'import foo; foo.bar()'? Я отримую іншу поведінку, коли, здається, аргумент -c ігнорується в першому випадку.
Абрам

29

Я написав невеликий маленький скрипт Python, який можна дзвонити з командного рядка bash. Він приймає назву модуля, класу та методу, який ви хочете викликати, та параметри, які ви хочете передати. Я називаю це PyRun і відмовився від розширення .py і зробив його виконуваним за допомогою chmod + x PyRun, щоб я міг просто викликати його швидко, як слід:

./PyRun PyTest.ClassName.Method1 Param1

Збережіть це у файлі під назвою 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)

Ось зразок модуля, який показує, як він працює. Це зберігається у файлі під назвою 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")

Спробуйте запустити наступні приклади:

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

Зазначимо останній приклад уникнення дужок, що передаються в кортеж, як єдиний параметр другого методу.

Якщо ви передасте занадто мало параметрів для того, що потрібно методу, ви отримаєте помилку. Якщо ви пропустите занадто багато, вона ігнорує макси. Модуль повинен бути в поточній робочій папці, поставити PyRun можна будь-де на вашому шляху.


2
Це приємно, але насправді це не відповідь на питання.
Френсіс Колас

14
Дозволю собі не погодитися; це саме питання. Він запитав, як ви запускаєте функцію з файлу, і саме це робить.
Джозеф Гальярдо

Чи можете ви пояснити, що робить біт про cmd_folder?
RyanDay

26

додайте цей фрагмент в нижню частину сценарію

def myfunction():
    ...


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

Тепер ви можете зателефонувати до своєї функції, запустивши

python myscript.py myfunction

Це працює, тому що ви передаєте аргумент командного рядка (рядок імені функції) у localsсловник із поточною таблицею локальних символів. Парафези в кінці змусять викликати функцію.

update: якщо ви хочете, щоб функція приймала параметр з командного рядка, ви можете перейти sys.argv[2]так:

def myfunction(mystring):
    print mystring


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

Таким чином, біг python myscript.py myfunction "hello"виведе hello.


Чи можливо для цього методу прийняти параметр функції? Такі якmyfunction(12)
майор майора

@MajorMajor Я оновив відповідь, щоб включити, як це зробити
Ноам Хакер

чи є така небезпека, що це робить у живому виробництві? Наче хочеться зробити це як одиничне тестування.
Арді

9

Давайте зробимо це трохи легше на собі і просто скористаємося модулем ...

Спробуйте: pip install compago

Тоді пиши:

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

Потім використовуйте так:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Примітка. Наразі в Python 3 є помилка , але вона чудово працює з Python 2.

Edit: навіть найкращий варіант, на мій погляд , є модуль вогню від Google , який дозволяє легко передавати аргументи функції. Він встановлюється за допомогою pip install fire. З їх GitHub:

Ось простий приклад.

import fire

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

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

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

Потім з командного рядка можна запустити:

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

+1. Вогонь навіть є спосіб виклику функції без зміни сценарію: python -m fire file_name method_name. Він також має вбудований аргпарсер.
користувач3265569

6

Цікаво, що якщо метою було надрукувати на консолі командного рядка або виконати якусь іншу хвилинову операцію python, ви можете передавати вхід в інтерпретатор python так:

echo print("hi:)") | python

а також файли труб ..

python < foo.py

* Зауважте, що розширення не повинно бути .py для другого, щоб воно працювало. ** Також зауважте, що для баш може вам знадобитися втекти персонажів

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

Розглядаючи приклад foo.py із прикладом hello (), саме так можна використовувати його із вищезгаданою ідеєю. echo import foo;foo.hello() | python
Аріндам Ройховдурі

Чи є спосіб передати аргументи командного рядка цим методом?
sparkonhdfs

1
Для третього прикладу FWIW, наступний пристрій є дещо чистішим:echo 'print("hi:)")' | python
user3166580


4

У мене була вимога використовувати різні утиліти python (діапазон, рядок тощо) у командному рядку, і я написав інструмент pyfunc спеціально для цього. Ви можете використовувати його для збагачення досвіду використання командного рядка:

 $ 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

Завжди є можливість ввести python в командному рядку за допомогою команди python

потім імпортуйте файл так, щоб імпортувати example_file

потім запустіть команду example_file.hello ()

Це дозволяє уникнути дивної функції копіювання .pyc, яка з'являється щоразу, коли ви запускаєте python -c тощо.

Можливо, не так зручно, як однокомандна команда, але хороший швидкий виправлення тексту тексту з командного рядка і дозволяє використовувати python для виклику та виконання файлу.


1

Щось подібне: 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

Це працює в базі.

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

1

Нижче - файл Odd_Even_function.py, який має визначення функції.

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

Тепер для того, щоб зателефонувати в командний рядок нижче, це варіанти, які працювали для мене.

Параметри 1 Повний шлях exe \ python.exe -c "імпортувати Odd_Even_function; Odd_Even_function.OE (100)"

Варіант 2 Повний шлях exe \ python.exe -c "від імпорту Odd_Even_function OE; OE (100)"

Дякую.


0

Цю функцію неможливо запустити з командного рядка, оскільки вона повертає значення, яке буде без змін. Ви можете видалити повернення та замість цього використовувати друк


-2

Скористайтеся інструментом python-c ( встановіть програму python-c ) та просто напишіть:

$ python-c foo 'hello()'

або у випадку, якщо у ваших файлах python не зіткнеться ім'я функції:

$ python-c 'hello()'

-2

Спочатку потрібно зателефонувати до функції, як вони вам сказали, або фонтан нічого не відображатиме у висновку, після цього збережіть файл і скопіюйте шлях до файлу, клацнувши правою кнопкою миші до папки файлу та натисніть на «Скопіювати файл», потім перейдіть до терміналу і напишіть: - cd "шлях файлу" - python "ім'я файлу, наприклад (main.py)", після чого він покаже вихід вашого коду.


-4

Зробіть своє життя простішим, встановіть Spyder. Відкрийте файл і запустіть його (натисніть зелену стрілку). Після цього ваш hello()метод визначений і відомий консолі IPython, тому ви можете викликати його з консолі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.