เรียกใช้ฟังก์ชันจากบรรทัดคำสั่ง


363

ฉันมีรหัสนี้:

def hello():
    return 'Hi :)'

ฉันจะเรียกใช้สิ่งนี้โดยตรงจากบรรทัดคำสั่งได้อย่างไร


21
คุณอาจมีความหมายแทนprint "Hi :)" return 'Hi :)'
Tamás

คำตอบ:


567

ด้วยอาร์กิวเมนต์-c (คำสั่ง) (สมมติว่าไฟล์ของคุณมีชื่อfoo.py):

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

อีกทางเลือกหนึ่งถ้าคุณไม่สนใจมลภาวะของ namespace:

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

และพื้นกลาง:

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

32
ฉันตั้งข้อสังเกตว่าใน windows shell คุณต้องมีเครื่องหมายคำพูดคู่แทนที่จะเป็นซิงเกิล $python -c "import foo;foo.hello()"
Arindam Roychowdhury

6
เกิดอะไรขึ้นถ้าไฟล์ไม่ได้อยู่ในไดเรกทอรีท้องถิ่นหรือใน PYTHONPATH?
Konstantin

2
คำตอบที่สองคือคำตอบทั่วไป ฉันมีสคริปต์ที่กำหนดฟังก์ชั่นของลูกค้าหลายคนและเรียกเพียงหนึ่งขึ้นอยู่กับความต้องการของฉัน
xappppp

1
ด้วยเหตุผลบางอย่างสิ่งนี้ไม่ได้ผลสำหรับฉันในขณะที่แทนที่print foo.hello()ด้วยprint(foo.hello())ทำ ฉันไม่มีความรู้ของหลามที่จะอธิบายว่าทำไมจึงเป็นเช่นนี้ดังนั้นหากคนอื่นสามารถอธิบายสิ่งที่เกิดขึ้นได้นั่นจะเป็นที่ชื่นชมอย่างมาก
Jasper

2
@Aakanksha ขอบคุณสำหรับคำอธิบายและแน่นอนว่าเหมาะสม ดูเหมือนว่าถูกต้องหรือไม่ที่จะแก้ไขคำตอบเพื่อรวมวงเล็บ? นั่นจะทำให้มันเข้ากันได้กับ python 2 และ 3 ถ้าฉันไม่เข้าใจผิด (ในช่วงเวลาเช่นนี้ฉันอยากจะให้คำแนะนำแก้ไข)
Jasper

130

เพียงวางที่hello()ด้านล่างของฟังก์ชันและมันจะทำงานเมื่อคุณทำpython your_file.py

สำหรับวิธีแก้ปัญหาแบบ neater คุณสามารถใช้สิ่งนี้:

if __name__ == '__main__':
    hello()

ด้วยวิธีนี้ฟังก์ชันจะทำงานเฉพาะเมื่อคุณเรียกใช้ไฟล์ไม่ใช่เมื่อคุณนำเข้าไฟล์


3
และhello()จะเกิดอะไรขึ้นหากมีการโต้แย้งที่ควรจะได้รับจากบรรทัดคำสั่ง?
ไม่ระบุตัวตน

2
ในกรณีนั้นคุณสามารถส่งsys.argvวิธีการ หรือเข้าถึงได้จากวิธีสวัสดี
Wolph

3
ข้อแตกต่างระหว่างคำตอบนี้กับโซลูชันการนำเข้า foo คือ import foo อนุญาตให้เรียกฟังก์ชันโดยพลการใน foo โดยไม่ต้องแก้ไข foo
plafratt

เป็นเรื่องจริง แต่ฉันจะไม่แนะนำวิธีแก้ปัญหานั้นนอกเหนือจากวัตถุประสงค์ในการทดสอบ
Wolph

@ Wolph เฮ้กับโครงสร้างนี้ฉันจะรันฟังก์ชันแยก (ไม่รวมอยู่ในhello()) และเรียกใช้จากบรรทัดคำสั่งได้อย่างไร
Souvik Ray

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.pypython -m myfile

คำอธิบายบางอย่างที่นี่: __name__เป็นพิเศษหลามตัวแปรที่เก็บชื่อของโมดูลในขณะนี้กำลังดำเนินการยกเว้น"__main__"เมื่อโมดูลจะเริ่มต้นจากบรรทัดคำสั่งซึ่งในกรณีนี้มันจะกลายเป็น


2
ความแตกต่างระหว่างpython -m foo -c 'foo.bar()'และpython -c 'import foo; foo.bar()'คืออะไร? ฉันได้รับพฤติกรรมที่แตกต่างกันซึ่งดูเหมือนว่าอาร์กิวเมนต์ -c จะถูกละเว้นในกรณีแรก
Abram

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

โปรดสังเกตตัวอย่างสุดท้ายของการหลีกเลี่ยงวงเล็บเพื่อส่งผ่านทูเปิลเป็นพารามิเตอร์เดียวไปยังเมธอด Second

หากคุณผ่านพารามิเตอร์น้อยเกินไปสำหรับสิ่งที่วิธีการที่คุณต้องการได้รับข้อผิดพลาด ถ้าคุณผ่านมากเกินไปมันจะไม่สนใจสิ่งที่เพิ่มเข้ามา โมดูลจะต้องอยู่ในโฟลเดอร์การทำงานปัจจุบันทำให้ PyRun สามารถอยู่ที่ใดก็ได้ในเส้นทางของคุณ


2
มันดี แต่มันไม่ใช่คำตอบสำหรับคำถาม
Francis Colas

14
ฉันขอแตกต่าง มันเป็นคำถามที่แน่นอน เขาถามว่าคุณจะเรียกใช้ฟังก์ชันจากไฟล์ได้อย่างไรและนั่นคือสิ่งที่มันทำ
โจเซฟ Gagliardo

คุณช่วยอธิบายเกี่ยวกับ cmd_folder ว่าทำอะไรได้บ้าง?
RyanDay

26

เพิ่มตัวอย่างนี้ไปที่ด้านล่างของสคริปต์ของคุณ

def myfunction():
    ...


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

ตอนนี้คุณสามารถเรียกใช้ฟังก์ชันของคุณโดยเรียกใช้

python myscript.py myfunction

สิ่งนี้ได้ผลเพราะคุณกำลังส่งผ่านอาร์กิวเมนต์บรรทัดคำสั่ง (สตริงของชื่อฟังก์ชัน) ลงในlocalsพจนานุกรมที่มีตารางสัญลักษณ์โลคอลปัจจุบัน parantheses ที่ส่วนท้ายจะทำให้เรียกใช้ฟังก์ชัน

อัปเดต:หากคุณต้องการให้ฟังก์ชันยอมรับพารามิเตอร์จากบรรทัดคำสั่งคุณสามารถส่งผ่าน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 ฉันได้อัปเดตคำตอบเพื่อรวมวิธีการทำเช่นนี้แล้ว
Noam Hacker

อันตรายนี้ทำเช่นนี้ในการผลิตสดหรือไม่? ชอบที่จะทำให้มันเป็นการทดสอบหน่วย
Ardhi

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

แก้ไข:ตัวเลือกที่ดียิ่งขึ้นในความคิดของฉันคือโมดูลไฟโดย 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ไฟยังมีวิธีการเรียกฟังก์ชั่นโดยไม่ต้องเปลี่ยนสคริปต์: นอกจากนี้ยังมี argparser ในตัว
user3265569

6

น่าสนใจพอหากเป้าหมายคือการพิมพ์ไปยังคอนโซลบรรทัดคำสั่งหรือดำเนินการหลามแบบนาทีอื่น ๆ คุณสามารถไพพ์อินพุตลงในตัวแปลของไพ ธ อนได้ดังนี้

echo print("hi:)") | python

เช่นเดียวกับไฟล์ไปป์ ..

python < foo.py

* โปรดทราบว่าส่วนขยายไม่จำเป็นต้องเป็น. py สำหรับการทำงานครั้งที่สอง ** โปรดทราบด้วยว่าสำหรับทุบตีคุณอาจต้องหลบหนีจากตัวละคร

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

เมื่อพิจารณาตัวอย่าง foo.py พร้อมด้วย hello () นี่เป็นวิธีที่จะใช้กับแนวคิดด้านบน echo import foo;foo.hello() | python
Arindam Roychowdhury

มีวิธีการส่งผ่านในอาร์กิวเมนต์บรรทัดคำสั่งด้วยวิธีนี้หรือไม่
sparkonhdfs

1
FWIW ต่อไปนี้สะอาดขึ้นเล็กน้อยสำหรับตัวอย่างที่สาม:echo 'print("hi:)")' | python
3186580

5

หากคุณติดตั้งแพคเกจ runp ด้วยpip install runpการใช้งาน:

runp myfile.py hello

คุณสามารถค้นหาที่เก็บได้ที่: https://github.com/vascop/runp


1
โครงการเข้ากันไม่ได้กับ Python 3
dim8

4

ฉันมีความต้องการของการใช้ยูทิลิตี้หลามต่างๆ (ช่วง, สตริง, ฯลฯ ) ในบรรทัดคำสั่งและได้เขียนเครื่องมือ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")

ตอนนี้การเรียกจาก Command prompt ด้านล่างเป็นตัวเลือกที่ใช้งานได้สำหรับฉัน

ตัวเลือก 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 ( pip install python-c ) จากนั้นเขียน:

$ python-c foo 'hello()'

หรือในกรณีที่คุณไม่มีชื่อฟังก์ชันที่ขัดแย้งในไฟล์หลามของคุณ

$ python-c 'hello()'

-2

ก่อนอื่นคุณต้องเรียกใช้ฟังก์ชั่นตามที่พวกเขาบอกคุณหรือ founction จะไม่แสดงอะไรเลยในเอาต์พุตหลังจากนั้นให้บันทึกไฟล์และคัดลอกพา ธ ของไฟล์โดยคลิกขวาที่โฟลเดอร์ของไฟล์และคลิกที่ "copy file" ไปที่เทอร์มินัลแล้วเขียน: - cd "พา ธ ของไฟล์" - python "ชื่อของไฟล์เช่น (main.py)" หลังจากนั้นจะแสดงผลลัพธ์ของโค้ดของคุณ


-4

ทำให้ชีวิตของคุณง่ายขึ้นติดตั้ง Spyder เปิดไฟล์ของคุณแล้วเรียกใช้ (คลิกที่ลูกศรสีเขียว) หลังจากนั้นhello()วิธีการของคุณจะถูกกำหนดและรู้จักกับ IPython Console เพื่อให้คุณสามารถเรียกได้จากคอนโซล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.