φυβλαςのβλογ
บล็อกของ phyblas



การปรับแต่งการรัน python ผ่านคอมมานด์ไลน์โดยใช้มอดูล argparse
เขียนเมื่อ 2020/03/22 13:01


ไพธอนสามารถรันผ่านคอมมานด์ไลน์ได้ และสามารถใส่ค่าเพิ่มเข้ามาเพิ่มเข้าในโปรแกรมเพื่อให้เปลี่ยนผลการรันในแต่ละครั้งได้ ดังที่อธิบายไปในhttps://phyblas.hinaboshi.com/20190705

แต่นอกจากนี้แล้วไพธอนยังได้เตรียมมอดูล argparse ไว้ ซึ่งเอาไว้สำหรับปรับแต่งการรับค่าเข้าไปยังโปรแกรมเมื่อรันผ่านคอมมานด์ไลน์

นอกจาก argparse แล้วก็ยังมีมอดูลอื่นเช่น click และ fire ซึ่งถ้าใช้แล้วอาจสามารถเขียนง่ายกว่า argparse แต่ไม่ใช่มอดูลที่มีอยู่แต่แรก ต้องติดตั้งเพิ่ม ดังนั้นจึงไม่ได้ใช้กว้างขวางเท่า

ในบทความนี้จะอธิบายวิธีการใช้ argparse




การสร้างตัวแปรที่ป้อนเพิ่มเข้าโปรแกรม

รูปแบบหนึ่งในการรันผ่านคอมมานด์ไลน์ที่นิยมใช้ก็คือเติมค่าอาร์กิวเมนต์ คือตัวแปรบางอย่างที่ต้องการลงไป

ยกตัวอย่างเช่น ต้องการโปรแกรมที่รับค่าตัวแปรเป็นตัวเลข ๒​ ตัวคือ x กับ y โดยเขียนแบบนี้
๛ python alpaka.py -x 3 -y 7

แบบนี้จะหมายความว่ารันโปรแกรม alpaka.pyโดยให้ ค่า x เป็น 3 ค่า y เป็น 7

โปรแกรมในลักษณะแบบนี้สามารถเขียนได้โดยใช้ argparse แบบนี้
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x')
p.add_argument('-y')
pa = p.parse_args()
print(pa)
print('x เป็น %s, y เป็น %s'%(pa.x,pa.y))

ลองเอามารันจะได้ผลแบบนี้
๛ python alpaca.py -x 2 -y 4
Namespace(x='2', y='4')
x เป็น 2, y เป็น 4
๛ python alpaca.py -x 3 -y 7     
Namespace(x='3', y='7')
x เป็น 3, y เป็น 7

ตัวอย่างต่อจากนี้ก็ไปจะใช้ชื่อไฟล์ที่จะรันว่า alpaca.py แล้วก็สั่งรันในคอมมานด์ไลน์แล้วดูผลทันที เครื่องหมาย ๛ จะใช้แทนบรรทัดที่พิมพ์ ส่วนบรรทัดถัดมาคือผลลัพธ์ แบบในตัวอย่างนี้

ต่อไปเป็นคำอธิบายวิธีการเขียน

เริ่มแรกคือต้อง import มอดูล argparse เพื่อมาใช้ แล้วก็สร้างออบเจ็กต์ argparse.ArgumentParser ขึ้นมา ออบเจ็กต์นี้จะใช้เพื่อเป็นตัวกลางในการสร้างปรับแต่งการรันในคอมมานด์ไลน์

ต่อมาเอาออบเจ็กต์นี้มาใช้ โดยการใช้เมธอด .add_argument() จะเป็นการสร้างตัวแปรที่ต้องการรับจากคอมมานด์ไลน์ขึ้นมา

จากนั้นใช้เมธอด .parse_args() จะได้ตัวออบเจ็กต์ Namespace ที่เก็บค่าตัวแปรที่รับมา และค่าตัวแปรก็จะเก็บอยู่ในแอตทริบิวต์ของออบเจ็กต์นั้นตามชื่อ เอามาใช้ในโปรแกรมได้

ชื่อตัวแปรจะตั้งชื่อเป็นอะไรก็ได้ แต่มีบางชื่อที่ห้ามใช้ เพราะไปซ้ำกับที่มีอยู่แล้ว เช่น -h หรือ --help เพราะนี่เป็นคำสั่งสำหรับแสดงคำอธิบายในการใช้ (จะอธิบายถึงทีหลัง)




การกำหนดชนิดข้อมูลของตัวแปร

ค่าตัวแปรที่รับมาปกติจะอยู่ในรูปของสายอักขระ แต่นอกจากนั้นแล้วเราสามารถกำหนดชนิดของตัวแปร เช่น int float ลงไปได้โดยใส่คีย์เวิร์ด type แล้วก็จะถูกแปลงเป็นชนิดนั้นให้เอง แต่ถ้าไม่ใส่จะเป็น str (สายอักขระ)

ตัวอย่างการตั้งชนิดข้อมูลให้ตัวแปร
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x')
p.add_argument('-y',type=int)
p.add_argument('-z',type=float)
pa = p.parse_args()
print(pa)
print(type(pa.x))
print(type(pa.y))
print(type(pa.z))
๛ python alpaca.py -x 3 -y 5 -z 7
Namespace(x='3', y=5, z=7.0)
<class 'str'>
<class 'int'>
<class 'float'>

ที่จริงแล้ว type ไม่ได้ใช้ได้แค่พวกชนิดข้อมูลทั่วไป สามารถใส่เป็นฟังก์ชันที่กำหนดเองก็ได้ เช่นลองแทนด้วยฟังก์ชันที่ใส่แล้วยาวขึ้น ๒ เท่า และมีการแต่งเติมอักษรทางซ้ายขวา
import argparse

def f(s):
    return '^*-'+s*2+'-*^'

p = argparse.ArgumentParser()
p.add_argument('-x',type=f)
print(p.parse_args())
๛ python alpaca.py -x คิระคิระ
Namespace(x='^*-คิระคิระคิระคิระ-*^')

เมื่อกำหนด type แล้ว ค่าที่รับเข้าไปก็จะถูกผ่านเข้าไปในฟังก์ชันนั้นแล้วค่าที่คืนกลับจากฟังก์ชันก็จะกลายเป็นค่าตัวแปรนั้น




ค่าตั้งต้นของตัวแปร

ตัวแปรที่กำหนดขึ้นมานั้นจะใส่ค่าหรือไม่ใส่ก็ได้ ถ้าไม่ได้ใส่ค่าเข้าไปก็จะได้ None
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x')
p.add_argument('-y')
pa = p.parse_args()
print(pa)
๛ python alpaca.py
Namespace(x=None, y=None)
๛ python alpaca.py -x 32
Namespace(x='32', y=None)
๛ python alpaca.py -y 23
Namespace(x=None, y='23')

หากต้องการให้มีค่าตั้งต้นไม่ให้เป็น None ก็ใส่คีย์เวิร์ด default
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',default=9)
p.add_argument('-y',default=1)
print(p.parse_args())
๛ python alpaca.py -x 3
Namespace(x='3', y=1)
๛ python alpaca.py -y 31
Namespace(x=9, y='31')

หากใส่ required=True จะทำให้ตัวแปรนั้นจำเป็นต้องใส่ ถ้าไม่ใส่ก็จะ error
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',required=True)
p.add_argument('-y')
print(p.parse_args())
๛ python alpaca.py -y 1
usage: alpaca.py [-h] -x X [-y Y]
alpaca.py: error: the following arguments are required: -x

หากต้องการให้ค่าที่ใส่ได้จำกัดอยู่แค่บางค่าก็ใส่ลิสต์ของค่าที่จำกัดให้ใช้ได้ลงในคีย์เวิร์ด choices
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',choices=['ก','ข','ค'])
print(p.parse_args())

แบบนี้ถ้าใส่ค่าที่ไม่มีอยู่ในตัวเลือกก็จะ error
๛ python alpaca.py -x a
usage: alpaca.py [-h] [-x {ก,ข,ค}]
alpaca.py: error: argument -x: invalid choice: 'a' (choose from 'ก', 'ข', 'ค')




ชื่อของตัวแปร

สามารถตั้งชื่อให้ตัวแปรมีชื่อหลายชื่อได้โดยใส่หลายชื่อลงไปทีเดียว เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x','-w')
p.add_argument('-y','-z')
print(p.parse_args())

แบบนี้เวลาใช้ ถ้าใส่เป็น -w ก็จะเหมือนกับใส่ -x และถ้าใส่ -z ก็จะเหมือนกับใส่ -y อย่างไรก็ตาม ตัวแปรที่ได้จะเป็นชื่อตามที่กำหนดลงไปเป็นตัวแรก
๛ python alpaca.py -w 5            
Namespace(x='5', y=None)
๛ python alpaca.py -x 5
Namespace(x='5', y=None)
๛ python alpaca.py -z 7 -w 5
Namespace(x='5', y='7')

ถ้าหากใส่ตัวที่แทนตัวเดียวกันซ้ำ ตัวที่ใส่ทีหลัง (อยู่ทางขวา) จะถูกใช้
๛ python alpaca.py -w 17 -z 21 -x 6
Namespace(x='6', y='21')
๛ python alpaca.py -x 6 -w 17 -z 21
Namespace(x='17', y='21')

ชื่อตัวแปรไม่จำเป็นต้องเป็นแค่อักษรตัวเดียว อาจจะเป็นคำก็ได้ แต่โดยทั่วไปแล้วถ้าไม่ใช่อักษรตัวเดียวมักจะใช้ขีด ๒ ขีดแทน เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('--uke')
p.add_argument('--seme')
print(p.parse_args())
๛ python alpaca.py --uke a --seme b
Namespace(seme='b', uke='a')

วิธีเขียนแบบหนึ่งที่อาจเจอบ่อยก็คือตั้งให้เขียนได้ ๒ แบบ ทั้งย่อตัวเดียวและเป็นคำ เพียงแต่กรณีที่มีทั้งตัวที่ขึ้นต้นด้วย ๑ ขีด - และ ๒ ขีด -- อยู่พร้อมกันแบบนี้ ชื่อตัวแปรหลักที่ได้จะเป็นตัวที่ใช้ ๒ ขีด -- แม้ว่าจะใส่ตัว ๒ ขีดไว้ทีหลังก็ตาม เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('-u','--uke')
p.add_argument('-s','--seme')
print(p.parse_args())
๛ python alpaca.py -u x -s y       
Namespace(seme='y', uke='x')

นอกจากนี้แล้ว หากต้องการกำหนดชื่อตัวแปรให้ต่างไปจากที่เขียนในคอมมานด์ไลน์ก็ทำได้โดยใส่คีย์เวิร์ด dest
import argparse

p = argparse.ArgumentParser()
p.add_argument('-u','--uke',dest='ukete')
p.add_argument('-s','--seme',dest='semete')
print(p.parse_args())
๛ python alpaca.py -u x -s y
Namespace(semete='y', ukete='x')




ตัวแปรที่ไม่ต้องใส่ค่า สนแค่ว่ามีหรือไม่มี

ถ้าต้องการตัวแปรที่ไม่จำเป็นต้องใส่ค่าอะไร แค่สนว่ามีการใส่ตัวแปรนั้นไปด้วยหรือเปล่า แบบนี้ใช้คีย์เวิร์ด action เพื่อทำได้

ให้ใส่ action เป็น store_const แล้วใส่ค่า const เป็นค่าที่จะให้เป็นเมื่อมีใส่ และหากต้องการให้มีค่าเมื่อไม่ใส่ด้วยก็ใส่ที่ default เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',action='store_const',const=1,default=5)
p.add_argument('-y',action='store_const',const=2)
p.add_argument('-z',action='store_const',const=3,default=4)
print(p.parse_args())
๛ python alpaca.py -x
Namespace(x=1, y=None, z=4)
๛ python alpaca.py -z -y
Namespace(x=5, y=2, z=3)

จะเห็นว่าเมื่อใช้ action='store_const' แบบนี้แล้ว ข้างหลังตัวแปรจะไม่ต้องใส่ค่าลงไป ใส่ลงไปโดดๆ และตำแหน่งต่อมาก็ตามด้วยตัวแปรตัวอื่นต่อได้เลย

หากต้องการตัวแปรที่เป็น True หรือ False อาจใช้ action เป็น store_true หรือ store_false

โดย store_true จะให้ค่า True เมื่อมีการใส่ และให้ False เมื่อไม่ใส่ ส่วน store_false จะกลับกัน คือให้ค่า True เมื่อไม่มีการใส่ และให้ False เมื่อใส่ อย่างไรก็ตามถ้ามีการใส่ค่า default ก็จะเป็นค่านั้นแทนเมื่อไม่มีการใส่
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',action='store_true')
p.add_argument('-y',action='store_false')
p.add_argument('-z',action='store_true',default=5)
print(p.parse_args())
๛ python alpaca.py -z
Namespace(x=False, y=True, z=True)
๛ python alpaca.py -x -y
Namespace(x=True, y=False, z=5)

ถ้ากำหนด action เป็น count จะเป็นการนับจำนวนว่ามีการใส่ตัวนั้นกี่ครั้ง สำหรับตัวแปรขีดเดียวแบบนี้จะเขียนติดๆกันไปก็ได้ ถ้าไม่ใส่เลยจะได้ None ถ้าไม่ได้กำหนดค่า default
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',action='count')
p.add_argument('-y',action='count')
p.add_argument('-z',action='count',default=0)
print(p.parse_args())
๛ python alpaca.py -x -x
Namespace(x=2, y=None, z=0)
๛ python alpaca.py -xyxyzx
Namespace(x=3, y=2, z=1)
๛ python alpaca.py -xyx -zyzzy
Namespace(x=2, y=3, z=3)




การรับตัวแปรเป็นลิสต์

หากใส่ action เป็น append จะทำให้ค่าตัวแปรได้เป็นลิสต์ โดยใส่ซ้ำกี่ตัวก็จะได้ค่าที่ใส่นั้นมาใส่ในลิสต์
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',action='append')
p.add_argument('-y',action='append',type=int)
print(p.parse_args())
๛ python alpaca.py -x ไก่ -x ไข่ -y 1 -x ควาย -y 7
Namespace(x=['ไก่', 'ไข่', 'ควาย'], y=[1, 7])
๛ python alpaca.py -x นึง -x ส่อง -x ซั่ม
Namespace(x=['นึง', 'ส่อง', 'ซั่ม'], y=None)

ถ้า action เป็น append_const จะเป็นตัวแปรที่ไม่ต้องมีการป้อนค่าตามมา แต่จะนับจำนวนแล้วได้ลิสต์ของค่าที่ระบุใน const เป็นจำนวนตามเท่านั้น ถ้าไม่ใส่เลยจะได้ None
import argparse

p = argparse.ArgumentParser()
p.add_argument('-a',action='append_const',const='เอ',default=[])
p.add_argument('-b',action='append_const',const='บี')
print(p.parse_args())
๛ python alpaca.py -aa   
Namespace(a=['เอ', 'เอ'], b=None)
๛ python alpaca.py -bb
Namespace(a=[], b=['บี', 'บี'])
๛ python alpaca.py -baba    
Namespace(a=['เอ', 'เอ'], b=['บี', 'บี'])

นอกจากนี้ถ้ากำหนด nargs ก็จะทำให้ได้เป็นค่าเป็นลิสต์ที่มีขนาดตามจำนวนที่ระบุ โดยต้องใส่ค่าหลังจากนั้นตามจำนวน และต้องใส่จำนวนเท่านั้นพอดี ใส่เกินหรือขาดก็จะ error
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',nargs=2)
p.add_argument('-y',nargs=3)
p.add_argument('-z',nargs=1)
print(p.parse_args())
๛ python alpaca.py -x 3 3 -y 2 2 1 -z 3
Namespace(x=['3', '3'], y=['2', '2', '1'], z=['3'])
๛ python alpaca.py -x 4 5 -y 7 5 1
Namespace(x=['4', '5'], y=['7', '5', '1'], z=None)
๛ python alpaca.py -x 8 17
Namespace(x=['8', '17'], y=None, z=None)
๛ python alpaca.py -x 3 3 -y 2 2
usage: alpaca.py [-h] [-x X X] [-y Y Y Y] [-z Z]
alpaca.py: error: argument -y: expected 3 arguments
๛ python alpaca.py -x 4 5 7
usage: alpaca.py [-h] [-x X X] [-y Y Y Y] [-z Z]
alpaca.py: error: unrecognized arguments: 7

หากต้องการให้เป็นลิสต์ที่ไม่จำกัดจำนวน ก็อาจใส่เป็น *
import argparse

p = argparse.ArgumentParser()
p.add_argument('-x',nargs='*')
print(p.parse_args())
๛ python alpaca.py -x        
Namespace(x=[])
๛ python alpaca.py -x 4 3 2 1
Namespace(x=['4', '3', '2', '1'])
๛ python alpaca.py -x 4 3 2
Namespace(x=['4', '3', '2'])
๛ python alpaca.py
Namespace(x=None)

หรืออาจใส่เป็น + ถ้าต้องการให้ต้องมีอย่างน้อยตัวนึง แบบนี้ถ้ามีตัวแปรนั้นแล้วไม่ใส่ค่าอะไรต่อเลยก็จะ error
import argparse

p = argparse.ArgumentParser()
p.add_argument('-y',nargs='+')
print(p.parse_args())
๛ python alpaca.py -y        
usage: alpaca.py [-h] [-y Y [Y ...]]
alpaca.py: error: argument -y: expected at least one argument
๛ python alpaca.py -y 8
Namespace(y=['8'])
๛ python alpaca.py     
Namespace(y=None)

ถ้าใส่เป็น ? จะไม่เป็นลิสต์ แต่ได้เป็นตัวแปรที่จะไม่ใส่ หรือใส่เฉยๆ หรือใส่พร้อมป้อนค่า ก็ได้ ถ้าไม่ใส่จะได้ค่า default ถ้าใส่จะได้ค่าตามที่ระบุใน const ถ้าใส่ก็จะได้ค่าตามนั้น
import argparse

p = argparse.ArgumentParser()
p.add_argument('-o',nargs='?',const='โอ',default='เอ็กซ์')
print(p.parse_args())
๛ python alpaca.py -o
Namespace(o='โอ')
๛ python alpaca.py -o "โอเอ็กซ์"
Namespace(o='โอเอ็กซ์')
๛ python alpaca.py
Namespace(o='เอ็กซ์')




ตัวแปรที่รับค่าตามลำดับ

นอกจากจะสร้างตัวแปรที่ต้องใส่ชื่อเวลาป้อนค่าแล้ว ยังสามารถสร้างตัวแปรที่ได้ค่าโดยขึ้นกับลำดับด้วย วิธีการสร้างคล้ายเดิม แค่ไม่ต้องใส่ - หรือ -- นำหน้าเวลาสร้าง เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('tuaraek')
p.add_argument('tuatopai')
p.add_argument('tuatopaiik')
print(p.parse_args())
๛ python alpaca.py ตัวแรก ตัวต่อไป ตัวต่อไปอีก
Namespace(tuaraek='ตัวแรก', tuatopai='ตัวต่อไป', tuatopaiik='ตัวต่อไปอีก')

แบบนี้ตัวแปรจะรับค่าที่ใส่ต่อจากชื่อโปรแกรม และค่าของตัวแปรแต่ละตัวจะเป็นไปตามลำดับที่ใส่

สามารถใส่ตัวแปรทั้งแบบป้อนตามชื่อและแบบป้อนตามลำดับไปได้พร้อมกัน และเวลาป้อนค่าจะใส่อันไหนก่อนก็ได้
p = argparse.ArgumentParser()
p.add_argument('a')
p.add_argument('-b')
p.add_argument('-c')
p.add_argument('d')
print(p.parse_args())
๛ python alpaca.py อา ดา -b บา -c คา
Namespace(a='อา', b='บา', c='คา', d='ดา')
๛ python alpaca.py อา -b เบ -c เซ เด
Namespace(a='อา', b='เบ', c='เซ', d='เด')
๛ python alpaca.py -c คะ -b บะ อะ ดะ
Namespace(a='อะ', b='บะ', c='คะ', d='ดะ')




การใช้ไฟล์เป็นค่าป้อนเข้าให้ตัวแปร

ถ้าต้องใช้ไฟล์เป็นค่าป้อนเข้าให้ตัวแปรให้ใส่ type ตัวแปรนั้นเป็น argparse.FileType() โดยในวงเล็บใส่โหมด เช่น r คืออ่าน w คือเขียน (เพียงแต่ว่า r เป็นค่าตั้งต้นอยู่แล้ว จะละไว้ก็ได้)

ตัวแปรที่ได้จะสามารถนำมาใช้ได้เหมือนเวลาเปิดไฟล์ด้วย open() คือถ้าเปิดโหมดอ่านก็ใช้ .read() หรือ .readline() เพื่ออ่านข้อความจากไฟล์ได้ เปิดโหมดเขียนก็ใช้ .write() เพื่อเขียนข้อความใส่ไฟล์ได้

ตัวอย่าง เปิดไฟล์ขึ้นมาอ่าน
import argparse

p = argparse.ArgumentParser()
p.add_argument('--fr',type=argparse.FileType())
pa = p.parse_args()
print(pa)
print(pa.fr.read())
pa.fr.close()
๛ python alpaca.py --fr mochi.txt
Namespace(fr=<_io.TextIOWrapper name='mochi.txt' mode='r' encoding='UTF-8'>)
(เนื้อหาในไฟล์นี้)

ตัวอย่างการเปิดไฟล์เพื่อเขียนข้อความลงไป
import argparse

p = argparse.ArgumentParser()
p.add_argument('--fw',type=argparse.FileType('w'))
pa = p.parse_args()
print(pa)
pa.fw.write('ยัดข้อความลงไฟล์')
pa.fw.close()
๛ python alpaca.py --fw machi.txt
Namespace(fw=<_io.TextIOWrapper name='kaki.txt' mode='w' encoding='UTF-8'>)




การดูและใส่เพิ่มคำอธิบายโปรแกรม

หากพิมพ์ชื่อไฟล์แล้วตามด้วย -h หรือ --help จะมีคำอธิบายโปรแกรมขึ้นมา ซึ่งบอกให้รู้ว่ามีตัวแปรอะไรบ้าง เช่น
import argparse

p = argparse.ArgumentParser()
p.add_argument('e')
p.add_argument('-b')
p.add_argument('-c')
p.add_argument('p')
print(p.parse_args())
๛ python alpaca.py -h
usage: alpaca.py [-h] [-b B] [-c C] e p

positional arguments:
  e
  p

optional arguments:
  -h, --help  show this help message and exit
  -b B
  -c C

ตัวแปรแบบตามลำดับจะแสดงอยู่ในส่วนของ positional arguments ส่วนตัวแปรแบบตามชื่อจะอยู่ที่ optional arguments โดยตรงนี้จะมี -h --help อยู่ด้วยเสมอ เป็นสิ่งที่มีอยู่แต่แรกแล้ว

ตรง usage นี้ปกติจะถูกสร้างให้โดยอัตโนมัติโดยแสดงชื่อโปรแกรมและแนะนำตัวแปรที่เราใช้คร่าวๆ

ในที่นี้ B C ที่อยู่ทางขวาของ -b -c ใช้แทนตัวค่าที่ต้องการใส่เข้าไป โดยปกติจะถูกตั้งให้อัตโนมัติเป็นตัวพิมพ์ใหญ่ของชื่อนั้น

แต่หากต้องการเปลี่ยนเป็นชื่อที่ต้องการก็ได้โดยใส่คีย์เวิร์ด metavar (เพียงแต่ก็ไม่ได้มีผลอะไรต่อโปรแกรม แค่เปลี่ยนเวลาแสดงผลในคำอธิบายเท่านั้น)
import argparse

p = argparse.ArgumentParser()
p.add_argument('-a','--anime',metavar='x')
p.add_argument('-g','--game')
p.parse_args()
python alpaca.py -h
usage: alpaca.py [-h] [-a x] [-g GAME]

optional arguments:
  -h, --help            show this help message and exit
  -a x, --anime x
  -g GAME, --game GAME

ในที่นี้ตัวแปรหลัง -a ถ้าไม่ใส่ metavar ก็คงจะเป็น ANIME แต่ใส่ metavar เป็น x จึงแทนด้วย x แทน

ในส่วนของชื่อโปรแกรมซึ่งแสดงอยู่ใน usage ปกติจะเป็นชื่อไฟล์ ในที่นี้คือ alpaca.py แต่สามารถเปลี่ยนใหม่ได้โดยเติมคีย์เวิร์ด prog
import argparse

p = argparse.ArgumentParser(prog='อัลปากา')
p.parse_args()
๛ python alpaca.py -h
usage: อัลปากา [-h]

optional arguments:
  -h, --help  show this help message and exit

ถ้าอยากพิมพ์ข้อความอธิบายจากภายในตัวโปรแกรมเองเลยโดยไม่ต้องใช้ -h หรือ --help ก็ใช้เมธอด .print_help() ได้
import argparse

p = argparse.ArgumentParser()
p.print_help()
๛ python alpaca.py   
usage: alpaca.py [-h]

optional arguments:
  -h, --help  show this help message and exit

ถ้าใช้เมธอด .print_usage() จะแสดงส่วน usage
import argparse

p = argparse.ArgumentParser()
p.print_usage()
๛ python alpaca.py             
usage: alpaca.py [-h]

.print_help() กับ .print_usage() จะเป็นการแสดงค่าออกมาทันที แต่หากต้องการให้เป็นสายอักขระ เพื่อจะเอามาใช้ทำอะไรก่อน แทนที่จะแสดงค่าทันที ก็อาจใช้ format_help() กับ format_usage()
import argparse

p = argparse.ArgumentParser()
print(p.format_help().split('\n'))
print(p.format_usage().split('\n'))
๛ python alpaca.py
['usage: alpaca.py [-h]', '', 'optional arguments:', '  -h, --help  show this help message and exit', '']
['usage: alpaca.py [-h]', '']

หากอยากเขียนคำอธิบาย usage เป็นอย่างอื่นทับไปแทน usage ที่มีอยู่แล้วแต่แรกก็ทำได้โดยใส่คีย์เวิร์ด usage
import argparse

p = argparse.ArgumentParser(usage='ใช้ไปเหอะไม่ต้องไรมาก')
p.parse_args()
๛ python alpaca.py -h
usage: ใช้ไปเหอะไม่ต้องไรมาก

optional arguments:
  -h, --help  show this help message and exit

สามารถเพิ่มคำอธิบายตัวโปรแกรมไปโดยใส่คีย์เวิร์ด description และ epilog ใน ArgumentParser ส่วนคำอธิบายตัวแปรแต่ละตัวใส่ลงคีย์เวิร์ด help

ตัวอย่างการใช้
import argparse

p = argparse.ArgumentParser(description='อัลปากาน่ารัก',epilog='อัลปากาไปแล้ว')
p.add_argument('equador',help='เอกวาดอร์')
p.add_argument('-b','--bo','--bolivia',help='โบลีเวีย',metavar='b')
p.add_argument('--chile',help='ชีเล',metavar='c')
p.add_argument('peru',help='เปรู')
p.parse_args()
๛ python alpaca.py -h
usage: alpaca.py [-h] [-b b] [--chile c] equador peru

อัลปากาน่ารัก

positional arguments:
  equador               เอกวาดอร์
  peru                  เปรู

optional arguments:
  -h, --help            show this help message and exit
  -b b, --bo b, --bolivia b
                        โบลีเวีย
  --chile c             ชีเล

อัลปากาไปแล้ว

คำอธิบายใน description จะปรากฏด้านบน ส่วนใน epilog จะปรากฏปิดท้าย

สามารถที่จะไม่ให้ใช้ -h หรือ --help เป็นคำอธิบายได้โดยใส่คีย์เวิร์ด add_help=False แบบนี้ตัวแปร -h และ --help ก็สามารถเอาไปใช้ทำอย่างอื่นแทนได้
import argparse

p = argparse.ArgumentParser(add_help=False)
p.add_argument('-h')
p.add_argument('--help')
pa = p.parse_args()
print(pa)
๛ python alpaca.py -h 1 --help 2
Namespace(h='1', help='2')




การเปลี่ยนอักษรนำหน้าจาก - เป็นอย่างอื่น

ปกติพวกตัวแปรที่ใส่ค่าตามชื่อจะขึ้นต้นด้วย - แต่ว่าก็สามารถเปลี่ยนให้เป็นอย่างอื่นแทนได้โดยระบุที่คีย์เวิร์ด prefix_chars ใน ArgumentParser สามารถใส่หลายตัวพร้อมกัน
import argparse

p = argparse.ArgumentParser(prefix_chars='%~+')
p.add_argument('+a')
p.add_argument('%%aa')
p.add_argument('~~aaa')
print(p.parse_args())
๛ python alpaca.py +a 1 %%aa 2 ~~aaa 3
Namespace(a='1', aa='2', aaa='3')

help เองก็จะไม่ได้ใช้เป็น -h และ --help แล้ว แต่จะเปลี่ยนเป็นนำด้วยอักษรที่ใส่เป็นตัวแรกใน prefix_chars ในที่นี้คือ %
๛ python alpaca.py %h
usage: alpaca.py [%h] [+a A] [%%aa AA] [~~aaa AAA]

optional arguments:
  %h, %%help  show this help message and exit
  +a A
  %%aa AA
  ~~aaa AAA




การเปลี่ยนค่าตั้งต้นของตัวแปรทั้งหมด

ปกติถ้าตัวแปรไหนที่ไม่ได้ใส่ค่าจะเป็น None หรือไม่ก็เป็นไปตามที่กำหนดใน default ถ้าหากใส่ไว้

แต่เราสามาตั้งค่าตั้งต้นสำหรับให้ใช้กับทุกค่าแทน None ได้ โดยใส่คีย์เวิร์ด argument_default ใน ArgumentParser (เพียงแต่ตัวไหนใส่ค่า default ก็จะใช้ค่าตามนั้นเป็นค่าตั้งต้นแทน)
import argparse

p = argparse.ArgumentParser(argument_default=1)
p.add_argument('-s')
p.add_argument('-t',default=2)
print(p.parse_args())
๛ python alpaca.py
Namespace(s=1, t=2)

หากใส่ argument_default=argparse.SUPPRESS จะทำให้ถ้าตัวแปรไหนไม่ได้ใส่ก็จะไม่ปรากฏเลย ยกเว้นจะมีการตั้งค่า default ไว้ที่ตัวนั้น
import argparse

p = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
p.add_argument('-s')
p.add_argument('-t',default=2)
p.add_argument('-u')
print(p.parse_args())
๛ python alpaca.py -u 3
Namespace(t=2, u='3')
๛ python alpaca.py
Namespace(t=2)




การย่อชื่อตัวแปร

ชื่อตัวแปรที่ยาวๆนั้นปกติเวลาใช้งานจริงจะสามารถเขียนย่อสั้นได้ ตราบใดที่ไม่ซ้ำกับตัวอื่นโปรแกรมก็จะรู้ว่าหมายถึงตัวไหนโดยอัตโนมัติ แต่ถ้าคำที่ใส่ไปซ้ำกัน ๒ ตัวขึ้นไปจึงจะ error
import argparse

p = argparse.ArgumentParser()
p.add_argument('--atar')
p.add_argument('--atrapar')
p.add_argument('--abrazar')
p.add_argument('--batallar')
print(p.parse_args())
๛ python alpaca.py --b 1 --ab 1  
Namespace(abrazar='1', atar=None, atrapar=None, batallar='1')
๛ python alpaca.py --ata 1 --atr 1
Namespace(abrazar=None, atar='1', atrapar='1', batallar=None)
๛ python alpaca.py --at 1         
usage: alpaca.py [-h] [--atar ATAR] [--atrapar ATRAPAR] [--abrazar ABRAZAR]
                 [--batallar BATALLAR]
alpaca.py: error: ambiguous option: --at could match --atar, --atrapar

แต่ถ้าไม่ต้องการให้สามารถย่อแบบนี้ได้ สามารถใส่ allow_abbrev=False ก็จะทำให้ต้องใส่ชื่อเต็มเท่านั้น
import argparse

p = argparse.ArgumentParser(allow_abbrev=False)
p.add_argument('--aparar')
print(p.parse_args())
๛ python alpaca.py --aparar 1
Namespace(aparar='1')
๛ python alpaca.py --aparar
usage: alpaca.py [-h] [--aparar APARAR]
alpaca.py: error: argument --aparar: expected one argument




การสร้างกลุ่มตัวแปรที่ให้เลือกใส่แค่ตัวใดตัวหนึ่งในกลุ่ม

หากมีตัวแปรหลายตัวที่ต้องการจับเป็นกลุ่มให้เลือกใส่ได้แค่ตัวเดียวสามารถทำได้โดยสร้างกลุ่มขึ้นมาด้วยเมธอด .add_mutually_exclusive_group() แล้วจะได้ออบเจ็กต์ตัวกลุ่ม จากนั้นจึงค่อยใช้ .add_argument() กับตัวกลุ่ม

ตัวอย่าง
import argparse

p = argparse.ArgumentParser()
g = p.add_mutually_exclusive_group()
g.add_argument('-c')
g.add_argument('-k')
g.add_argument('-q')
print(p.parse_args())
๛ python alpaca.py -c กา
Namespace(c='กา', k=None, q=None)
๛ python alpaca.py -q กวา
Namespace(c=None, k=None, q='กวา')
๛ python alpaca.py
Namespace(c=None, k=None, q=None)
๛ python alpaca.py -k เก -q กวา
usage: alpaca.py [-h] [-c C | -k K | -q Q]
alpaca.py: error: argument -q: not allowed with argument -k

จะเห็นว่าใน c k q เมื่อใส่ ๒ ตัวจากในนี้ขึ้นไปก็จะเกิด error




สรุปคีย์เวิร์ดที่ใส่ได้ใน ArgumentParser

คีย์เวิร์ด ความหมาย ค่าตั้งต้น
prog ชื่อตัวโปรแกรม None
usage คำอธิบายวิธีใช้โปรแกรม None
description คำอธิบายโปรแกรม None
epilog คำอธิบายส่งท้ายโปรแกรม None
prefix_chars อักษรที่เป็นตัวนำหน้าชื่อตัวแปร None
argument_default ค่าตั้งต้นของทุกตัวแปร None
add_help ทำให้ -h และ --help เป็นตัวเลือกที่บอกคำอธิบาย True
allow_abbrev ให้ใช้ชื่อย่อได้ True




สรุปคีย์เวิร์ดที่ใส่ได้ใน .add_argument

คีย์เวิร์ด ความหมาย ค่าตั้งต้น
action รูปแบบของตัวแปร store
nargs กำหนดจำนวนข้อมูลในลิสต์ตัวแปร
const ค่าคงที่เมื่อใช้ action หรือ nargs
default ค่าตั้งต้น
type ชนิดข้อมูลตัวแปร str
choices กำหนดค่าที่จำกัดให้เป็นได้
required กำหนดว่าเป็นตัวแปรที่ต้องมีแน่นอนหรือไม่ False
help คำอธิบายตัวแปรเพิ่มเติม
metavar ชื่อแทนตัวแปรที่ปรากฏในคำอธิบาย
dest ชื่อพรอเพอร์ตี




อ้างอิง



-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python
-- คอมพิวเตอร์ >> shell

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- opencv
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
maya
javascript
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
เรียนภาษาจีน
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
หลักการเขียนทับศัพท์ภาษาจีนกวางตุ้ง
การใช้ unix shell เบื้องต้น ใน linux และ mac
หลักการเขียนทับศัพท์ภาษาจีนกลาง
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
บันทึกการเที่ยวสวีเดน 1-12 พ.ค. 2014
แนะนำองค์การวิจัยและพัฒนาการสำรวจอวกาศญี่ปุ่น (JAXA)
เล่าประสบการณ์ค่ายอบรมวิชาการทางดาราศาสตร์โดยโซวเคนได 10 - 16 พ.ย. 2013
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
บันทึกการเที่ยวญี่ปุ่นครั้งแรกในชีวิต - ทุกอย่างเริ่มต้นที่สนามบินนานาชาติคันไซ
หลักการเขียนทับศัพท์ภาษาญี่ปุ่น
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ
ทำไมถึงอยากมาเรียนต่อนอก
เหตุผลอะไรที่ต้องใช้ภาษาวิบัติ?

ไทย

日本語

中文