Komut satırından fonksiyonu çalıştır


363

Bu kodu var:

def hello():
    return 'Hi :)'

Bunu doğrudan komut satırından nasıl çalıştırabilirim?


21
Muhtemelen print "Hi :)"bunun yerine demek istediniz return 'Hi :)'.
Tamás

Yanıtlar:


567

İle -c (komut) argüman (dosya adı verilir varsayarak foo.py):

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

Alternatif olarak, ad alanı kirliliğini önemsemiyorsanız:

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

Ve orta yol:

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

32
Windows kabuğunda, tek yerine çift alıntı yapmanız gerektiğini belirttim. $python -c "import foo;foo.hello()"
Arindam Roychowdhury

6
Dosya yerel dizinde veya PYTHONPATH'de değilse ne olur?
Konstantin

2
İkincisi daha genel bir cevaptır. Birden fazla müşteri işlevi tanımlı bir komut dosyası var ve ihtiyacıma bağlı olarak sadece bir tane çağrı
xappppp

1
Nedense, bu değiştirirken, benim için işe yaramadı print foo.hello()ile print(foo.hello())yaptı. Bunun nedenini açıklamak için python bilgim yok, bu yüzden başka biri neler olup bittiğini açıklayabilirse, bu büyük mutluluk duyacaktır
Jasper

2
@Aakanksha Açıklama için teşekkürler ve bu kesinlikle mantıklı. Cevabı parantezleri içerecek şekilde düzenlemek doğru görünüyor mu? Yanılmıyorsam bu hem python 2 hem de 3 ile uyumlu olur. (Böyle anlarda, düzenleme önerisinde bulunmak isterdim.)
Jasper

130

Sadece hello()fonksiyonun altına bir yere koyun ve bunu yaptığınızdapython your_file.py

Daha temiz bir çözüm için bunu kullanabilirsiniz:

if __name__ == '__main__':
    hello()

Bu şekilde, dosyayı içe aktardığınızda değil, yalnızca dosyayı çalıştırırsanız işlev yürütülür.


3
Ve ya hello()komut satırı tarafından sağlanması gereken argümanları alırsa ?
Anonim

2
Bu durumda sys.argvyönteme gönderebilirsiniz . Veya merhaba yönteminden erişin
Wolph

3
Bu cevap ve import foo çözümü arasındaki bir fark, import foo'nun foo'yu değiştirmeden foo'da keyfi bir fonksiyon çağırmaya izin vermesidir.
plafratt

Bu doğru, ancak bu çözümü test amaçlarının ötesinde tavsiye etmem
Wolph

@Wolph hey bu yapı ile, ayrı bir işlevi (içeride dahil değildir hello()) nasıl çalıştırabilirim ve komut satırından nasıl çalıştırabilirim?
Souvik Ray

66

python -c 'from myfile import hello; hello()'burada myfilePython betiğinizin taban adı ile değiştirilmelidir. (Örneğin, myfile.pyolur myfile).

Ancak, hello()Python betiğinizdeki "kalıcı" ana giriş noktanız varsa , bunu yapmanın genel yolu aşağıdaki gibidir:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

Bu, komut dosyasını basitçe python myfile.pyveya çalıştırarak yürütmenizi sağlar python -m myfile.

Burada bazı açıklamalar: modülün komut satırından başlatılması haricinde , __name__yürütülmekte olan modülün adını tutan özel bir Python değişkeni, bu durumda olur ."__main__"


2
Arasındaki fark nedir python -m foo -c 'foo.bar()'ve python -c 'import foo; foo.bar()'? Ben -c argümanı ilk durumda göz ardı gibi görünüyor farklı davranış olsun.
Abram

29

Bir bash komut satırından çağrılabilen hızlı küçük bir Python betiği yazdım. Aramak istediğiniz modülün, sınıfın ve yöntemin adını ve geçmek istediğiniz parametrelerin adını alır. Bunu PyRun olarak adlandırıyorum ve .py uzantısını bıraktım ve chmod + x PyRun ile çalıştırılabilir yaptım, böylece aşağıdaki gibi hızlı bir şekilde çağırabilirim:

./PyRun PyTest.ClassName.Method1 Param1

Bunu PyRun adlı bir dosyaya kaydedin

#!/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)

Nasıl çalıştığını gösteren örnek bir modül. Bu, PyTest.py adlı bir dosyaya kaydedilir:

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

Şu örnekleri çalıştırmayı deneyin:

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

İkinci yöntemin tek parametresi olarak bir demet içinde geçmek için parantezlerden kaçmanın son örneğine dikkat edin.

Yöntemin gereksinim duyduğu şey için çok az parametre iletirseniz bir hata alırsınız. Çok fazla geçerseniz, ekstraları yok sayar. Modül geçerli çalışma klasöründe olmalıdır, koymak PyRun yolunuzun herhangi bir yerinde olabilir.


2
Güzel, ama gerçekten sorunun cevabı değil.
Francis Colas

14
Naçizane size katılmıyorum; asıl soru bu. Dosyadan bir işlevi nasıl çalıştırdığınızı sordu ve bunun tam olarak ne yaptığını sordu.
Joseph Gagliardo

Cmd_folder hakkında biraz ne yaptığını açıklayabilir misiniz?
RyanDay

26

bu snippet'i komut dosyanızın altına ekleyin

def myfunction():
    ...


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

Artık çalıştırarak işlevinizi çağırabilirsiniz

python myscript.py myfunction

Bu locals, geçerli bir yerel sembol tablosuna sahip bir sözlüğe komut satırı bağımsız değişkenini (işlev adının bir dizesi) geçirdiğiniz için çalışır . Sondaki parantezler işlevi çağırır.

update: işlevin komut satırından bir parametre kabul etmesini istiyorsanız, şu şekilde iletebilirsiniz sys.argv[2]:

def myfunction(mystring):
    print mystring


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

Bu şekilde, çalışan python myscript.py myfunction "hello"çıktı alınacaktır hello.


Bu yöntemin işlev için bir parametre kabul etmesi mümkün müdür? Gibimyfunction(12)
Binbaşı Binbaşı

@MajorMajor Bunun nasıl yapılacağını içerecek şekilde cevabı güncelledim
Noam Hacker

canlı prodüksiyonda bunu yapmak bir tehlike midir? Gibi bir birim testi yapmak istiyorum.
Ardhi

9

Bunu kendimiz için biraz daha kolaylaştıralım ve sadece bir modül kullanalım ...

Deneyin: pip install compago

Sonra yaz:

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

Sonra şöyle kullanın:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Not: Şu anda Python 3'te bir hata var , ancak Python 2 ile harika çalışıyor.

Düzenleme: Bence daha iyi bir seçenek, bence Google tarafından modül ateşi de işlev argümanları geçmeyi kolaylaştırır. İle kurulur pip install fire. GitHub'larından:

İşte basit bir örnek.

import fire

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

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

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

Ardından, komut satırından şunları çalıştırabilirsiniz:

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

+1. Yangın senaryoyu değiştirmeden bir işlevi çağırmak için bir yol vardır: python -m fire file_name method_name. Ayrıca yerleşik bir argparser vardır.
user3265569

6

İlginçtir ki, hedef komut satırı konsoluna yazdırmak veya başka bir dakika python işlemi gerçekleştirmekse, girişi python yorumlayıcısına şu şekilde aktarabilirsiniz:

echo print("hi:)") | python

yanı sıra boru dosyaları ..

python < foo.py

* İkincinin çalışması için uzantının .py olması gerekmediğini unutmayın. ** Ayrıca bash için karakterlerden kaçmanız gerekebileceğini unutmayın

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

Foo.py ile merhaba () örneği göz önüne alındığında, yukarıdaki fikirle bu şekilde kullanılabilir. echo import foo;foo.hello() | python
Arindam Roychowdhury

Bu yöntemle komut satırı bağımsız değişkenlerini iletmenin bir yolu var mı?
sparkonhdfs

1
FWIW, üçüncü örnek için aşağıdakiler biraz daha temiz:echo 'print("hi:)")' | python
user3166580


4

Komut satırında çeşitli python yardımcı programları (aralık, dize, vb.) Kullanma gereksinimi vardı ve özellikle bunun için araç pyfunc yazmıştı . Komut satırı kullanım deneyiminizi zenginleştirmek için kullanabilirsiniz:

 $ 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

Her zaman komut ile komut satırında python girmek için bir seçenek piton

sonra dosyanızı içe aktarın example_file dosyasını içe aktarın

sonra komutu example_file.hello () ile çalıştırın

Bu, python -c vs.'yi her çalıştırdığınızda kesilen garip .pyc kopyalama işlevini önler.

Tek bir komut kadar kullanışlı olmayabilir, ancak komut satırından bir dosyayı metinlemek için iyi bir hızlı düzeltme ve dosyanızı aramak ve yürütmek için python kullanmanıza izin verir.


1

Bunun gibi bir şey: 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

Bu bash'da çalışır.

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

1

Aşağıda, işlevin tanımına sahip Odd_Even_function.py dosyası bulunmaktadır.

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

Şimdi aşağıdaki Komut isteminden aynı şeyi çağırmak benim için çalışan seçenekler.

Seçenekler 1 exe \ python.exe -c dosyasının tam yolu "Odd_Even_function dosyasını içe aktarın; Odd_Even_function.OE (100)"

Seçenek 2 exe \ python.exe -c dosyasının tam yolu "Odd_Even_function import OE; OE (100)"

Teşekkürler.


0

Bu işlev, ele alınmayacak bir değer döndürdüğü için komut satırından çalıştırılamaz. İadeyi kaldırabilir ve bunun yerine yazdırmayı kullanabilirsiniz


-2

Kullanım piton-c (aracı pip piton-c yüklemek ) ve daha sonra sadece yazmak:

$ python-c foo 'hello()'

veya python dosyalarınızda işlev adı çakışması olmaması durumunda:

$ python-c 'hello()'

-2

Önce işlevi söyledikleri gibi çağırmanız gerekir veya işlev çıktıda hiçbir şey göstermez, bundan sonra dosyayı kaydedin ve dosyanın klasörünü sağ tıklayıp "dosyayı kopyala" yı tıklatarak dosyanın yolunu kopyalayın. terminale gidin ve şunu yazın: - cd "dosyanın yolu" - python "örneğin dosyanın adı (main.py)" sonra kodunuzun çıktısını görüntüler.


-4

Hayatınızı kolaylaştırın, Spyder'ı yükleyin. Dosyanızı açın ve çalıştırın (yeşil oku tıklayın). Daha sonra hello()yönteminiz IPython Konsolu tarafından tanımlanır ve bilinir, böylece onu konsoldan çağırabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.