Jalankan fungsi dari baris perintah


363

Saya punya kode ini:

def hello():
    return 'Hi :)'

Bagaimana saya menjalankan ini langsung dari baris perintah?


21
Mungkin yang Anda maksudkan print "Hi :)"bukan return 'Hi :)'.
Tamás

Jawaban:


567

Dengan argumen -c (perintah) (dengan asumsi file Anda bernama foo.py):

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

Atau, jika Anda tidak peduli dengan polusi namespace:

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

Dan jalan tengah:

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

32
Saya mencatat bahwa pada shell windows, Anda memerlukan penawaran ganda alih-alih tunggal. $python -c "import foo;foo.hello()"
Arindam Roychowdhury

6
Bagaimana jika file tersebut tidak ada di direktori lokal atau di PYTHONPATH?
Konstantin

2
Yang kedua adalah jawaban yang lebih umum. Saya memiliki skrip yang menetapkan beberapa fungsi pelanggan, dan hanya memanggil satu tergantung pada kebutuhan saya
xappppp

1
Untuk beberapa alasan, ini tidak berhasil untuk saya, sementara menggantinya print foo.hello()dengan print(foo.hello()). Saya tidak memiliki pengetahuan python untuk menjelaskan mengapa ini terjadi, jadi jika orang lain dapat menjelaskan apa yang sedang terjadi, itu akan sangat dihargai
Jasper

2
@Aakanksha Terima kasih atas penjelasannya, dan itu jelas masuk akal. Apakah sepertinya benar untuk mengedit jawaban dengan menyertakan tanda kurung? Itu akan membuatnya kompatibel dengan kedua python 2 dan 3 jika saya tidak salah. (Pada saat-saat seperti ini, saya ingin dapat membuat saran edit.)
Jasper

130

Cukup letakkan di hello()suatu tempat di bawah fungsi dan itu akan dijalankan ketika Anda melakukannyapython your_file.py

Untuk solusi yang lebih rapi, Anda dapat menggunakan ini:

if __name__ == '__main__':
    hello()

Dengan begitu fungsi hanya akan dieksekusi jika Anda menjalankan file, bukan ketika Anda mengimpor file.


3
Dan bagaimana jika hello()mengambil argumen yang harus disediakan oleh baris perintah?
Anonim

2
Dalam hal ini Anda dapat mengirim sys.argvke metode. Atau akses dari metode halo
Wolph

3
Satu perbedaan antara jawaban ini dan solusi import foo adalah impor foo memungkinkan memanggil fungsi arbitrer di foo tanpa memodifikasi foo.
plafrat

Itu benar, tetapi saya tidak akan merekomendasikan solusi yang melampaui tujuan pengujian
Wolph

@Wolph hei dengan struktur ini, bagaimana cara menjalankan fungsi terpisah (tidak termasuk di dalam hello()) dan menjalankannya dari baris perintah?
Souvik Ray

66

python -c 'from myfile import hello; hello()'di mana myfileharus diganti dengan nama sandi skrip Python Anda. (Misalnya, myfile.pymenjadi myfile).

Namun, jika hello()titik masuk utama "permanen" Anda dalam skrip Python Anda, maka cara biasa untuk melakukan ini adalah sebagai berikut:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Ini memungkinkan Anda untuk menjalankan skrip hanya dengan menjalankan python myfile.pyatau python -m myfile.

Beberapa penjelasan di sini: __name__adalah variabel Python khusus yang menyimpan nama modul yang sedang dieksekusi, kecuali ketika modul dimulai dari baris perintah, dalam hal ini menjadi "__main__".


2
Apa perbedaan antara python -m foo -c 'foo.bar()'dan python -c 'import foo; foo.bar()'? Saya mendapatkan perilaku yang berbeda di mana tampaknya argumen -c diabaikan dalam kasus pertama.
Abram

29

Saya menulis skrip Python kecil cepat yang dapat dipanggil dari baris perintah bash. Dibutuhkan nama modul, kelas dan metode yang ingin Anda panggil dan parameter yang ingin Anda sampaikan. Saya menyebutnya PyRun dan meninggalkan ekstensi .py dan membuatnya dieksekusi dengan chmod + x PyRun sehingga saya bisa memanggilnya dengan cepat sebagai berikut:

./PyRun PyTest.ClassName.Method1 Param1

Simpan ini dalam file yang disebut 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)

Berikut adalah contoh modul untuk menunjukkan cara kerjanya. Ini disimpan dalam file bernama 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")

Coba jalankan contoh-contoh ini:

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

Perhatikan contoh terakhir melarikan diri tanda kurung untuk lulus dalam tuple sebagai satu-satunya parameter untuk metode Kedua.

Jika Anda melewatkan terlalu sedikit parameter untuk metode apa yang Anda butuhkan, Anda mendapatkan kesalahan. Jika Anda melewati terlalu banyak, ia mengabaikan ekstra. Modul harus berada di folder saat ini, menempatkan PyRun bisa di mana saja di jalur Anda.


2
Itu bagus, tapi itu bukan jawaban untuk pertanyaan itu.
Francis Colas

14
Saya mohon untuk berbeda; itulah pertanyaannya. Dia bertanya bagaimana Anda menjalankan fungsi dari file dan itulah yang dilakukan.
Joseph Gagliardo

Bisakah Anda jelaskan apa yang dilakukan bit tentang cmd_folder?
RyanDay

26

tambahkan potongan ini ke bagian bawah skrip Anda

def myfunction():
    ...


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

Anda sekarang dapat memanggil fungsi Anda dengan menjalankan

python myscript.py myfunction

Ini berfungsi karena Anda meneruskan argumen baris perintah (string nama fungsi) ke locals, kamus dengan tabel simbol lokal saat ini. Tanda kurung pada akhirnya akan membuat fungsi dipanggil.

pembaruan: jika Anda ingin fungsi menerima parameter dari baris perintah, Anda bisa masuk sys.argv[2]seperti ini:

def myfunction(mystring):
    print mystring


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

Dengan cara ini, menjalankan python myscript.py myfunction "hello"akan menghasilkan hello.


Apakah mungkin metode ini menerima parameter untuk fungsi tersebut? Sepertimyfunction(12)
Mayor Mayor

@MajorMajor Saya telah memperbarui jawaban untuk memasukkan cara melakukan ini
Noam Hacker

apakah ini ada bahaya melakukan ini dalam produksi langsung? Seperti ingin menjadikannya sebagai unit test.
Ardhi

9

Mari kita buat ini sedikit lebih mudah pada diri kita dan cukup gunakan modul ...

Mencoba: pip install compago

Lalu menulis:

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

Kemudian gunakan seperti ini:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Catatan: Ada bug di Python 3 saat ini, tetapi berfungsi baik dengan Python 2.

Sunting: Pilihan yang lebih baik lagi, menurut saya adalah modul fire oleh Google yang membuatnya mudah untuk meneruskan argumen fungsi. Itu diinstal dengan pip install fire. Dari GitHub mereka:

Ini contoh sederhana.

import fire

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

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

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

Kemudian, dari baris perintah, Anda dapat menjalankan:

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

+1. Api bahkan memiliki cara untuk memanggil fungsi tanpa mengubah script: python -m fire file_name method_name. Ini juga memiliki argparser bawaan.
user3265569

6

Cukup menarik, jika tujuannya adalah untuk mencetak ke konsol baris perintah atau melakukan beberapa operasi python menit lainnya, Anda dapat menyalurkan input ke interpreter python seperti:

echo print("hi:)") | python

serta file pipa ..

python < foo.py

* Perhatikan bahwa ekstensi tidak harus .py agar yang kedua berfungsi. ** Juga perhatikan bahwa untuk bash Anda mungkin perlu melarikan diri dari karakter

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

Mempertimbangkan contoh foo.py dengan hello (), ini adalah bagaimana seseorang dapat menggunakannya dengan ide di atas. echo import foo;foo.hello() | python
Arindam Roychowdhury

Apakah ada cara untuk meneruskan argumen baris perintah dengan metode ini?
sparkonhdfs

1
FWIW, berikut ini sedikit lebih bersih untuk contoh ketiga:echo 'print("hi:)")' | python
user3166580


4

Saya memiliki persyaratan untuk menggunakan berbagai utilitas python (rentang, string, dll.) Pada baris perintah dan telah menulis alat pyfunc khusus untuk itu. Anda dapat menggunakannya untuk memperkaya pengalaman penggunaan baris perintah Anda:

 $ 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

Itu selalu merupakan opsi untuk memasukkan python di baris perintah dengan perintah python

kemudian impor file Anda jadi impor example_file

kemudian jalankan perintah dengan example_file.hello ()

Ini menghindari fungsi .pyc copy aneh yang muncul setiap kali Anda menjalankan python -c dll.

Mungkin tidak semudah perintah tunggal, tetapi perbaikan cepat yang baik untuk teks file dari baris perintah, dan memungkinkan Anda untuk menggunakan python untuk memanggil dan mengeksekusi file Anda.


1

Sesuatu seperti ini: 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

Ini bekerja di bash.

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

1

Di bawah ini adalah file Odd_Even_function.py yang memiliki definisi fungsi.

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

Sekarang untuk memanggil yang sama dari Command prompt di bawah ini adalah opsi yang berfungsi untuk saya.

Opsi 1 Path lengkap dari exe \ python.exe -c "import Odd_Even_function; Odd_Even_function.OE (100)"

Opsi 2 Path lengkap exe \ python.exe -c "dari Odd_Even_function import OE; OE (100)"

Terima kasih.


0

Fungsi ini tidak dapat dijalankan dari baris perintah karena mengembalikan nilai yang tidak akan ditangani. Anda dapat menghapus pengembalian dan menggunakan cetak sebagai gantinya


-2

Gunakan alat python-c ( pip install python-c ) dan kemudian cukup menulis:

$ python-c foo 'hello()'

atau jika Anda tidak memiliki bentrokan nama fungsi di file python Anda:

$ python-c 'hello()'

-2

Pertama, Anda harus memanggil fungsi seperti yang mereka katakan atau fungsi tidak akan menampilkan apa pun di output, setelah itu simpan file dan salin path file dengan klik kanan ke folder file dan klik "copy file" lalu buka terminal dan tulis: - cd "path file" - python "nama file misalnya (main.py)" setelah itu akan menampilkan output dari kode Anda.


-4

Buat hidup Anda lebih mudah, instal Spyder. Buka file Anda kemudian jalankan (klik panah hijau). Setelah itu hello()metode Anda didefinisikan dan dikenal oleh Konsol IPython, sehingga Anda dapat memanggilnya dari konsol.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.