Pythonã§ã¹ã¯ãªãããæžããšããã³ãã³ãã©ã€ã³ããåŒæ°ãæž¡ããŠå®è¡ãããå Žé¢ã¯ãããããŸããããæšæºã©ã€ãã©ãªã® `argparse` ãããµãŒãããŒãã£ã® `Click` ãªã©ãæ§ã ãªã©ã€ãã©ãªãååšããŸãããããã£ãšæ軜ã«ãç°¡åã«CLIãäœãããïŒããšæã£ãããšã¯ãããŸãããïŒ ð€
ãããªããªãã«ãããããªã®ããGoogleãéçºãã Python Fire ã§ãïŒðð¥
Python Fireã¯ããããæ°è¡ã®ã³ãŒããè¿œå ããã ãã§ãæ¢åã®Pythonã³ãŒãïŒé¢æ°ãã¯ã©ã¹ããªããžã§ã¯ããèŸæžãªã©ïŒãã³ãã³ãã©ã€ã³ã€ã³ã¿ãŒãã§ãŒã¹ïŒCLIïŒã«å€æã§ããç»æçãªã©ã€ãã©ãªã§ããåŒæ°ã®ããŒã¹åŠçããã«ãã¡ãã»ãŒãžã®çæãªã©ãèªåã§è¡ã£ãŠããããããéçºè ã¯æ¬æ¥ã®ããžãã¯å®è£ ã«éäžã§ããŸãã
ãã®ããã°èšäºã§ã¯ãPython Fireã®åºæ¬çãªäœ¿ãæ¹ãããå°ãå¿çšçãªäœ¿ãæ¹ããããŠãã®ã¡ãªããã»ãã¡ãªãããŸã§ã詳ãã解説ããŠãããŸãããã®èšäºãèªãã°ãããªããPython Fireã䜿ãããªããæ¥ã ã®éçºå¹çãçäžãã§ããã¯ãã§ãïŒð
ã€ã³ã¹ããŒã«
Python Fireã®ã€ã³ã¹ããŒã«ã¯éåžžã«ç°¡åã§ããpipã䜿ã£ãŠã€ã³ã¹ããŒã«ã§ããŸããç¹å¥ãªäŸåé¢ä¿ããããŸããïŒPythonãšpipãã€ã³ã¹ããŒã«ãããŠããã°OKïŒã
pip install fire
condaã䜿çšããŠããå Žåã¯ãconda-forgeãã£ã³ãã«ããã€ã³ã¹ããŒã«ã§ããŸãã
conda install fire -c conda-forge
ããã§æºåå®äºã§ãïŒæ©é䜿ã£ãŠã¿ãŸãããã
åºæ¬çãªäœ¿ãæ¹
Python Fireã®æ倧ã®é åã¯ããã®ã·ã³ãã«ãã§ããæ¢åã®ã³ãŒãã«æå°éã®å€æŽãå ããã ãã§CLIåã§ããŸãã
1. é¢æ°ãCLIåãã
æãåºæ¬çãªäœ¿ãæ¹ã¯ãåäžã®é¢æ°ãCLIãšããŠå ¬éããæ¹æ³ã§ãã
äŸãšããŠãæšæ¶ãããç°¡åãªé¢æ° `hello` ãæ〠`example.py` ãäœæããŸãã
# example.py
import fire
def hello(name="World"):
"""æå®ãããååã§æšæ¶ããŸãã"""
return f"Hello {name}!"
if __name__ == '__main__':
fire.Fire(hello)
ãã®ã¹ã¯ãªããã®æåŸã« `fire.Fire(hello)` ãè¿œå ããã ãã§ãããã㧠`hello` é¢æ°ãã³ãã³ãã©ã€ã³ããåŒã³åºããããã«ãªããŸãã
ã¿ãŒããã«ããå®è¡ããŠã¿ãŸãããã
# åŒæ°ãªãã§å®è¡ (ããã©ã«ãå€ "World" ã䜿ããã)
$ python example.py
Hello World!
# åŒæ°ãæå®ããŠå®è¡
$ python example.py David
Hello David!
# --name=value 圢åŒã§ãæå®å¯èœ
$ python example.py --name=Google
Hello Google!
ãã®ããã«ãé¢æ°åãæå®ããã«é¢æ°ã®åŒæ°ãçŽæ¥æž¡ãããšãã§ããŸããFireãèªåçã«åŒæ°ã解éããé©åãªåã®å€ïŒãã®å Žåã¯æååïŒãšããŠé¢æ°ã«æž¡ããŠãããŸãã
ð¡ ãã³ã: é¢æ°ã®docstringã¯ãèªåçæããããã«ãã¡ãã»ãŒãžã«äœ¿çšãããŸãã `–help` ãã©ã°ãä»ããŠå®è¡ãããšã䜿ãæ¹ã確èªã§ããŸãã
$ python example.py --help
INFO: Showing help with the command 'python example.py -- --help'.
NAME
example.py - æå®ãããååã§æšæ¶ããŸãã
SYNOPSIS
example.py [<name>]
POSITIONAL ARGUMENTS
name
Type: str
Default: 'World'
NOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
`–help` ã `-h` ãªãã·ã§ã³ã¯ãã³ãã³ãå šäœã ãã§ãªããåå¥ã®ã³ãã³ãïŒåŸè¿°ããã¯ã©ã¹ã®ã¡ãœãããªã©ïŒã«å¯ŸããŠã䜿çšã§ããŸãããã®å Žåããã©ã°ã®åã« `–` ã眮ãããšã§ãFireã®ãã©ã°ã§ããããšãæ瀺ããŸãã
# åå¥ã³ãã³ãã®ãã«ã衚瀺 (calculator.py double ã®ãã«ããèŠãäŸ)
$ python calculator.py double -- --help
2. ã¯ã©ã¹ãCLIåãã
ã¯ã©ã¹ã `fire.Fire()` ã«æž¡ããšããã®ã¯ã©ã¹ã®ã¡ãœããããµãã³ãã³ããšããŠå©çšã§ããããã«ãªããŸãã
ç°¡åãªèšç®æ©ã¯ã©ã¹ `Calculator` ãæ〠`calculator.py` ãäœæããŸãã
# calculator.py
import fire
class Calculator(object):
"""ç°¡åãªèšç®æ©ã¯ã©ã¹ã"""
def __init__(self, base=0):
self._base = base
print(f"Calculator initialized with base {self._base}")
def double(self, number):
"""äžããããæ°ã2åããŸãã"""
return 2 * number
def add(self, x, y):
"""2ã€ã®æ°ã足ãåãããŸãã"""
return x + y + self._base
def _private_method(self):
# ã¢ã³ããŒã¹ã³ã¢ã§å§ãŸãã¡ãœããã¯ããã©ã«ãã§ã¯å
¬éãããªã
return "This is private"
if __name__ == '__main__':
fire.Fire(Calculator)
ãããå®è¡ããŠã¿ãŸããããã¯ã©ã¹ã®ã¡ãœããåããµãã³ãã³ããšããŠèªèãããŸãã
# double ã¡ãœãããå®è¡
$ python calculator.py double 10
Calculator initialized with base 0
20
# --number=value 圢åŒã§ãåŒæ°ãæž¡ãã
$ python calculator.py double --number=15
Calculator initialized with base 0
30
# add ã¡ãœãããå®è¡ (äœçœ®åŒæ°)
$ python calculator.py add 5 3
Calculator initialized with base 0
8
# add ã¡ãœãããå®è¡ (ããŒã¯ãŒãåŒæ°)
$ python calculator.py add --x=7 --y=2
Calculator initialized with base 0
9
# ã³ã³ã¹ãã©ã¯ã¿åŒæ°ãæå®ããŠã¡ãœãããå®è¡
$ python calculator.py --base=10 add 5 3
Calculator initialized with base 10
18
# ãããã㣠(ã€ã³ã¹ã¿ã³ã¹å€æ°) ã«ã¢ã¯ã»ã¹ (ããã©ã«ãã§ã¯éå
Ž)
# fire.Fire(Calculator, command=['double', 'add']) ã®ããã«æ瀺çã«æå®ãããã
# --verbose ãã©ã°ã䜿ãããšã§ã¢ã¯ã»ã¹å¯èœã«ãªãå Žåããã (èŠç¢ºèª)
# $ python calculator.py _base # éåžžã¯ãšã©ãŒã«ãªã
# ãã©ã€ããŒãã¡ãœããã¯åŒã³åºããªã
# $ python calculator.py _private_method # ãšã©ãŒã«ãªã
ã¯ã©ã¹ã `fire.Fire()` ã«æž¡ããšããŸãã¯ã©ã¹ãã€ã³ã¹ã¿ã³ã¹åããããã®ã€ã³ã¹ã¿ã³ã¹ã®ã¡ãœãããåŒã³åºãããŸããã³ã³ã¹ãã©ã¯ã¿ (`__init__`) ã«åŒæ°ãããå Žåã¯ãã³ãã³ãã©ã€ã³ãã `–åŒæ°å=å€` ã®åœ¢åŒã§æž¡ãããšãã§ããŸããã¡ãœããã®åŒæ°ãåæ§ã«ãäœçœ®åŒæ°ãŸãã¯ããŒã¯ãŒãåŒæ° (`–åŒæ°å=å€`) ã§æž¡ããŸãã
â ïž æ³šæ: ã¢ã³ããŒã¹ã³ã¢ (`_`) ã§å§ãŸãã¡ãœãããããããã£ã¯ãããã©ã«ãã§ã¯CLIãšããŠå ¬éãããŸãããæå³çã«å ¬éãããå Žåã¯ãåŸè¿°ããèŸæžã䜿ãæ¹æ³ãªã©ãæ€èšããŠãã ããã
3. ã¢ãžã¥ãŒã«å šäœãCLIåãã
`fire.Fire()` ã«äœãåŒæ°ãæž¡ããªãå Žåããã®ã¹ã¯ãªããïŒã¢ãžã¥ãŒã«ïŒå ã§å®çŸ©ãããŠããå šãŠã®å ¬éå¯èœãªãªããžã§ã¯ãïŒé¢æ°ãã¯ã©ã¹ãå€æ°ãªã©ïŒãèªåçã«CLIãšããŠå ¬éãããŸãã
# tools.py
import fire
PI = 3.14159
def greet(name="User"):
return f"Hi, {name}!"
class Greeter:
def formal_greet(self, title, name):
return f"Good day, {title} {name}."
# ã¢ã³ããŒã¹ã³ã¢ã§å§ãŸããã®ã¯ç¡èŠããã
_INTERNAL_VAR = "secret"
if __name__ == '__main__':
fire.Fire() # åŒæ°ãªãã§åŒã³åºã
å®è¡äŸïŒ
# å€æ° PI ã®å€ã衚瀺
$ python tools.py PI
3.14159
# greet é¢æ°ãå®è¡
$ python tools.py greet Alice
Hi, Alice!
# Greeter ã¯ã©ã¹ã® formal_greet ã¡ãœãããå®è¡
# ã¯ã©ã¹å -> ã¡ãœããå ã®é ã§æå®
$ python tools.py Greeter formal_greet --title Dr. --name Bob
Good day, Dr. Bob.
# _INTERNAL_VAR ã¯è¡šç€ºãããªã
# $ python tools.py _INTERNAL_VAR # ãšã©ãŒ
ãã®æ¹æ³ã¯éåžžã«æ軜ã§ãããæå³ããªããªããžã§ã¯ããŸã§å ¬éãããŠããŸãå¯èœæ§ããããããå ¬éãã察象ãæ確ã«ãããå Žåã¯ãé¢æ°ãã¯ã©ã¹ãèŸæžãæ瀺çã«æž¡ãæ¹ãå®å šã§ãã
4. èŸæžã䜿ã£ãŠã³ãã³ããå®çŸ©ãã
è€æ°ã®é¢æ°ãç°ãªããªããžã§ã¯ããçµã¿åãããŠCLIãæ§ç¯ãããå ŽåãèŸæžã `fire.Fire()` ã«æž¡ãã®ã䟿å©ã§ããèŸæžã®ããŒãã³ãã³ãåãå€ã察å¿ããPythonãªããžã§ã¯ãïŒé¢æ°ãã¯ã©ã¹ãå€ãªã©ïŒã«ãªããŸãã
# commands.py
import fire
import math
def add(x, y):
return x + y
def subtract(x, y):
return x - y
class AdvancedMath:
def power(self, base, exp):
return math.pow(base, exp)
if __name__ == '__main__':
# ã³ãã³ãåãšå¯Ÿå¿ãããªããžã§ã¯ããèŸæžã§å®çŸ©
commands = {
'plus': add,
'minus': subtract,
'math': AdvancedMath, # ã¯ã©ã¹ãæž¡ãããšãå¯èœ
'version': '1.0.0' # æååãªã©ã®å€ãæž¡ãã
}
fire.Fire(commands)
å®è¡äŸïŒ
# 'plus' ã³ãã³ã (addé¢æ°) ãå®è¡
$ python commands.py plus 10 5
15
# 'minus' ã³ãã³ã (subtracté¢æ°) ãå®è¡
$ python commands.py minus 10 5
5
# 'math' ã³ãã³ã (AdvancedMathã¯ã©ã¹) ã® 'power' ã¡ãœãããå®è¡
$ python commands.py math power 2 8
256.0
# 'version' ã³ãã³ã (æåå) ã衚瀺
$ python commands.py version
1.0.0
èŸæžã䜿ãããšã§ãã³ãã³ãåãèªç±ã«èšå®ããããç°ãªãçš®é¡ã®ãªããžã§ã¯ããçµã¿åãããŠæè»ãªCLIãæ§ç¯ã§ããŸãã
åŒæ°ããŒã¹ã®æå
Python Fireã¯ãã³ãã³ãã©ã€ã³ããæž¡ãããåŒæ°ãè³¢ã解éããããšããŸãã
- æ°å€: `10`, `-5`, `3.14` ãªã©ã¯æ°å€ïŒintãŸãã¯floatïŒãšããŠè§£éãããŸãã
- æåå: ã¯ã©ãŒããªãã®åèª (`hello`, `world`) ããã¯ã©ãŒãã§å²ãŸããå€ (`”Hello World!”`, `’single quote’`) ã¯æååãšããŠè§£éãããŸãã
- ããŒã«å€: `–flag`, `–no-flag`, `–flag=true`, `–flag=false` ãªã©ã®åœ¢åŒã§ããŒã«å€ãæž¡ããŸãã
- ãªã¹ã/ã¿ãã«: `[1,2,3]`, `(a,b,c)` ã®ããã«è§æ¬åŒ§ãäžžæ¬åŒ§ã§å²ãŸããå€ã¯ãªã¹ããã¿ãã«ãšããŠè§£éãããŸããèŠçŽ éã«ã¹ããŒã¹ãããå Žåã¯ãå šäœãã¯ã©ãŒãã§å²ãå¿ èŠããããŸã (`”[1, 2, 3]”` ãªã©)ã
- èŸæž: `{‘key’:’value’, ‘num’:123}` ã®ããã«æ³¢æ¬åŒ§ã§å²ãŸããå€ã¯èŸæžãšããŠè§£éãããŸãããªã¹ã/ã¿ãã«ãšåæ§ã«ãã¹ããŒã¹ãå«ãå Žåã¯ã¯ã©ãŒããå¿ èŠã§ãã
äŸïŒ
# parser_example.py
import fire
def process_data(data, count, active=False, options=None):
print(f"Data: {data} (Type: {type(data)})")
print(f"Count: {count} (Type: {type(count)})")
print(f"Active: {active} (Type: {type(active)})")
print(f"Options: {options} (Type: {type(options)})")
if __name__ == '__main__':
fire.Fire(process_data)
# æååãæ°å€ãããŒã«å€ããªã¹ããæž¡ã
$ python parser_example.py my_string 10 --active '[item1, item2]'
Data: my_string (Type: <class 'str'>)
Count: 10 (Type: <class 'int'>)
Active: True (Type: <class 'bool'>)
Options: ['item1', 'item2'] (Type: <class 'list'>)
# èŸæžãæž¡ã (ã¯ã©ãŒããå¿
èŠ)
$ python parser_example.py data_dict 5 --options "{'mode':'fast', 'retries':3}"
Data: data_dict (Type: <class 'str'>)
Count: 5 (Type: <class 'int'>)
Active: False (Type: <class 'bool'>)
Options: {'mode': 'fast', 'retries': 3} (Type: <class 'dict'>)
# ããŒã«å€ã®ãã©ã° (å€ãçç¥ãããšTrue)
$ python parser_example.py data 1 --active
Data: data (Type: <class 'str'>)
Count: 1 (Type: <class 'int'>)
Active: True (Type: <class 'bool'>)
Options: None (Type: <class 'NoneType'>)
# --no-ãã©ã°å 㧠False ãæå®
$ python parser_example.py data 1 --no-active
Data: data (Type: <class 'str'>)
Count: 1 (Type: <class 'int'>)
Active: False (Type: <class 'bool'>)
Options: None (Type: <class 'NoneType'>)
Fireã¯Pythonã® `ast.literal_eval` ã«äŒŒãæ¹æ³ã§åŒæ°ãè©äŸ¡ããŸãããããæè»ãªè§£éãè¡ããŸãããã ããè€éãªãªããžã§ã¯ããæå³ããªãåå€æãçºçããå¯èœæ§ãããããã泚æãå¿ èŠã§ãã
é«åºŠãªäœ¿ãæ¹
Python Fireã«ã¯ãåºæ¬çãªäœ¿ãæ¹ä»¥å€ã«ã䟿å©ãªæ©èœãããã€ããããŸãã
1. 察話ã¢ãŒã (`–interactive`)
`–interactive` ãã©ã°ãä»ããŠã³ãã³ããå®è¡ãããšãã³ãã³ãå®è¡åŸã«Pythonã®å¯Ÿè©±åã·ã§ã«ïŒREPLïŒãèµ·åããŸãããã®ã·ã§ã«å ã§ã¯ãã³ãã³ãã®å®è¡çµæããã¹ã¯ãªããå ã§å®çŸ©ãããå€æ°ã»é¢æ°ã»ã¯ã©ã¹ãªã©ãå©çšå¯èœãªç¶æ ã§éå§ãããããããããã°ãåäœç¢ºèªã«éåžžã«äŸ¿å©ã§ãã âš
# interactive_example.py
import fire
message = "Initial message"
def update_message(new_msg):
global message
message = new_msg
return f"Message updated to: {message}"
def get_message():
return message
class Counter:
def __init__(self, start=0):
self.count = start
def increment(self, amount=1):
self.count += amount
return self.count
if __name__ == '__main__':
fire.Fire()
察話ã¢ãŒããè©ŠããŠã¿ãŸãããã
# update_message ãå®è¡ããåŸã«å¯Ÿè©±ã¢ãŒãã«å
¥ã
$ python interactive_example.py update_message "New content" -- --interactive
INFO: Running command: python interactive_example.py update_message 'New content' -- --interactive
Message updated to: New content
INFO: Entered interactive mode. Type q or quit to exit.
Fire behavior: > indicates command results. Variables are directly available.
>>> message # ã¹ã¯ãªããå
ã®å€æ°ã«ã¢ã¯ã»ã¹ã§ãã
'New content'
>>> get_message() # ã¹ã¯ãªããå
ã®é¢æ°ãåŒã³åºãã
'New content'
>>> result = _ # çŽåã®ã³ãã³ãã®å®è¡çµæ㯠_ ã«æ ŒçŽããã
>>> print(result)
Message updated to: New content
>>> c = Counter(10) # ã¹ã¯ãªããå
ã®ã¯ã©ã¹ã䜿ãã
>>> c.increment(5)
15
>>> quit # ã·ã§ã«ãçµäº
察話ã¢ãŒãã§ã¯ã `_` å€æ°ã«çŽåã®ã³ãã³ãã®å®è¡çµæãæ ŒçŽãããŸãããŸããã¹ã¯ãªããå ã®ã°ããŒãã«å€æ°ãé¢æ°ãã¯ã©ã¹ã«çŽæ¥ã¢ã¯ã»ã¹ã§ãããããç¶æ ã確èªããããè¿œå ã®æäœãè©Šãããããã®ã«åœ¹ç«ã¡ãŸãã
2. ã¡ãœãããã§ãŒã³
`fire.Fire()` ã«æž¡ãããªããžã§ã¯ãã®ã¡ãœãããå¥ã®ãªããžã§ã¯ããè¿ãå Žåããã®è¿ããããªããžã§ã¯ãã®ã¡ãœãããç¶ããŠåŒã³åºãããšãã§ããŸããããã«ãããã¡ãœããåŒã³åºããé£éãããããšãå¯èœã§ããð
# chain_example.py
import fire
class TextProcessor:
def __init__(self, text):
self.text = text
print(f"Initialized with: '{self.text}'")
def upper(self):
self.text = self.text.upper()
print(f"After upper: '{self.text}'")
return self # èªåèªèº«ãè¿ã
def add_suffix(self, suffix):
self.text += suffix
print(f"After add_suffix: '{self.text}'")
return self # èªåèªèº«ãè¿ã
def get_length(self):
print(f"Final text: '{self.text}'")
return len(self.text)
if __name__ == '__main__':
fire.Fire(TextProcessor)
å®è¡äŸïŒ
# ã³ã³ã¹ãã©ã¯ã¿ -> upper -> add_suffix -> get_length ãå®è¡
$ python chain_example.py "hello world" upper add_suffix --suffix="!!!" get_length
Initialized with: 'hello world'
After upper: 'HELLO WORLD'
After add_suffix: 'HELLO WORLD!!!'
Final text: 'HELLO WORLD!!!'
14
ã³ã³ã¹ãã©ã¯ã¿åŒæ° (`”hello world”`) ã `TextProcessor` ã«æž¡ãããã€ã³ã¹ã¿ã³ã¹ãçæãããŸãããã®åŸã`upper` ã¡ãœããã`add_suffix` ã¡ãœãã (`–suffix` ãã©ã°ã§åŒæ°ãæå®)ã`get_length` ã¡ãœãããé ã«åŒã³åºãããŠããŸããåã¡ãœããã `self` (ã€ã³ã¹ã¿ã³ã¹èªèº«) ãè¿ãããšã§ããã§ãŒã³ãå¯èœã«ãªã£ãŠããŸãã
3. ã³ãã³ãã®ã°ã«ãŒãå
ã¯ã©ã¹ãèŸæžããã¹ããããããšã§ãã³ãã³ããéå±€çã«ã°ã«ãŒãåã§ããŸããããã«ãããé¢é£ããã³ãã³ãããŸãšããŠæŽçããããè€éãªCLIãæ§ç¯ã§ããŸããð
# group_example.py
import fire
class Git:
def status(self):
return "On branch main. Nothing to commit, working tree clean."
def commit(self, message):
return f"Committing with message: '{message}'"
class Docker:
def build(self, tag="latest"):
return f"Building Docker image with tag: {tag}"
def run(self, image):
return f"Running Docker container: {image}"
class Tools:
def __init__(self):
self.git = Git()
self.docker = Docker()
def system_info(self):
import platform
return platform.system()
if __name__ == '__main__':
fire.Fire(Tools) # Toolsã¯ã©ã¹ãèµ·ç¹ãšãã
# ãŸãã¯ãèŸæžã§å®çŸ©ããŠãè¯ã
# fire.Fire({'git': Git, 'docker': Docker, 'sysinfo': system_info_func})
å®è¡äŸïŒ
# git ã°ã«ãŒãã® status ã³ãã³ããå®è¡
$ python group_example.py git status
On branch main. Nothing to commit, working tree clean.
# docker ã°ã«ãŒãã® build ã³ãã³ããå®è¡
$ python group_example.py docker build --tag v1.0
Building Docker image with tag: v1.0
# Tools ã¯ã©ã¹çŽäžã® system_info ã³ãã³ããå®è¡
$ python group_example.py system_info
# (å®è¡ç°å¢ã«ãã£ãŠ Darwin, Linux, Windows ãªã©ãåºåããã)
Darwin
`Tools` ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹å€æ° `git` ãš `docker` ããããããµãã³ãã³ãã°ã«ãŒããšãªãããã®äžã®ã¡ãœãã (`status`, `commit`, `build`, `run`) ãããã«ãµãã³ãã³ããšããŠåŒã³åºããããã«ãªã£ãŠããŸãã
4. ãã®ä»ã®ãã©ã°
Python Fireã«ã¯ãä»ã«ãããã€ãã®äŸ¿å©ãªãã©ã°ããããŸãããããã®ãã©ã°ã¯ãã³ãã³ããšåŒæ°ã®åŸã« `–` ã§åºåã£ãŠæå®ããŸãã
- `–separator=X`: ã¡ãœãããã§ãŒã³ãåŒæ°åã®åºåãæåãããã©ã«ãã®ãã€ãã³ (`-`) ããæå®ããæå `X` ã«å€æŽããŸããäŸãã° `–separator=_` ãšãããšã`my_command` ã®ããã«ã¢ã³ããŒã¹ã³ã¢åºåãã§ã¡ãœãããåŒã³åºããããã«ãªããŸãã
- `–trace`: ã³ãã³ããã©ã®ããã«è§£éãããå®è¡ããããã®è©³çŽ°ãªãã¬ãŒã¹æ å ±ã衚瀺ããŸãããããã°æã«åœ¹ç«ã¡ãŸãã
- `–verbose` / `-v`: ãã«ãã¡ãã»ãŒãžãªã©ã«ãã¢ã³ããŒã¹ã³ã¢ã§å§ãŸããã©ã€ããŒããªã¡ã³ããŒãå«ããŠè¡šç€ºããŸãã
- `–completion [shell]`: æå®ããã·ã§ã«ïŒbash, zshãªã©ïŒçšã®ã¿ãè£å®ã¹ã¯ãªãããçæããŸãã
# ãã¬ãŒã¹æ
å ±ã衚瀺
$ python calculator.py add 1 2 -- --trace
INFO: Running command: python calculator.py add 1 2 -- --trace
Fire trace:
1. Initial component: <class '__main__.Calculator'>
2. Instantiated class `Calculator`
3. Accessed member `add`
4. Called function `add` with args `(1, 2)`
3
ã¡ãªãããšãã¡ãªãã
Python Fireã¯éåžžã«äŸ¿å©ãªã©ã€ãã©ãªã§ãããä»ã®ããŒã«ãšåæ§ã«ã¡ãªãããšãã¡ãªããããããŸãã
ã¡ãªãã ð
- å§åçãªæ軜ã: æ¢åã®Pythonã³ãŒãã«å¯Ÿããå€æŽãæå°éã§æžã¿ãŸãã`import fire` ãš `fire.Fire(…)` ã®åŒã³åºããè¿œå ããã ãã§ãåºæ¬çãªCLIãå®æããŸãã
- åŠç¿ã³ã¹ãã®äœã: `argparse` ã `Click` ã®ãããªãã³ã¬ãŒã¿ãè€éãªèšå®ãèŠããå¿ èŠãã»ãšãã©ãããŸãããPythonã®åºæ¬çãªç¥èãããã°ããã«äœ¿ããŸãã
- æè»æ§: é¢æ°ãã¯ã©ã¹ãã¡ãœãããã¢ãžã¥ãŒã«ãèŸæžããªã¹ããªã©ãããããPythonãªããžã§ã¯ããCLIåã§ããŸãã
- èªåãã«ãçæ: docstringãèšè¿°ããŠããã°ããããèªåçã«ãã«ãã¡ãã»ãŒãžã«åæ ãããŸãã
- 察話ã¢ãŒã: `–interactive` ãã©ã°ã«ãã察話ã¢ãŒãã¯ããããã°ãåäœç¢ºèªãã¡ãã£ãšããè©Šè¡é¯èª€ã«éåžžã«åŒ·åã§ãã
- éçºå¹çã®åäž: ã©ã€ãã©ãªãããŒã«ã®éçºäžã«ããã®æ©èœãã³ãã³ãã©ã€ã³ããçŽ æ©ããã¹ãã§ããŸãã
ãã¡ãªãã ð
- æé»çãªåäœ: åŒæ°ã®å解éãã³ãã³ãã®æ¢çŽ¢ãªã©ãèªåã§è¡ããããããæã«æå³ããªãæåãããããšããããŸããç¹ã«è€éãªåŒæ°ãã³ãã³ãæ§é ã®å Žåãäºæãã¬ãšã©ãŒãçºçããå¯èœæ§ããããŸãã
- ã«ã¹ã¿ãã€ãºæ§ã®éç: `argparse` ã `Click` ã»ã©è©³çŽ°ãªã«ã¹ã¿ãã€ãºïŒåŒæ°ã®ããªããŒã·ã§ã³ã«ãŒã«ãè€éãªãªãã·ã§ã³å®çŸ©ãç¬èªã®ãšã©ãŒãã³ããªã³ã°ãªã©ïŒã¯ã§ããŸãããéåžžã«åã£ãCLIãäœãããå Žåã«ã¯ãæ©èœäžè¶³ãæãããããããŸããã
- åãã³ãã®ç¡èŠ: åŒæ°ã®åã¯ãé¢æ°ã®åãã³ãã§ã¯ãªããã³ãã³ãã©ã€ã³ããã®å ¥åå€ã«åºã¥ããŠèªåçã«è§£éãããŸããããã«ãããäºæããªãåå€æãçºçããããåãã³ãã«ããéç解æã®æ©æµãåãã«ããã£ããããå ŽåããããŸããïŒä»£æ¿ãšã㊠`jsonargparse` ãªã©ãæããããŸãïŒ
- äŸåé¢ä¿: æšæºã©ã€ãã©ãªã§ã¯ãªããããå©çšç°å¢ã« `fire` ã©ã€ãã©ãªãã€ã³ã¹ããŒã«ããå¿ èŠããããŸããïŒããã¯å€ãã®ãµãŒãããŒãã£ã©ã€ãã©ãªã«å ±éããŸããïŒ
Python Fireã¯ãç¹ã«å人ã®éçºããŒã«ãç°¡åãªã¹ã¯ãªãããã©ã€ãã©ãªã®ãã¹ãããããã¿ã€ãã³ã°ãªã©ãæ軜ããšã¹ããŒããéèŠãããå Žé¢ã§éåžžã«åŒ·åãªéžæè¢ãšãªããŸããäžæ¹ã§ãéåžžã«å ç¢ã§è€éãªCLIã¢ããªã±ãŒã·ã§ã³ãé åžããå Žåã«ã¯ã`argparse` ã `Click` ã®æ¹ãé©ããŠããå ŽåããããŸãã
ãŠãŒã¹ã±ãŒã¹ã»æŽ»çšäŸ ð¡
Python Fireã¯æ§ã ãªå Žé¢ã§æŽ»çšã§ããŸãã
- æ¥åžžçãªã¹ã¯ãªããã®CLIå: ãã¡ã€ã«æäœãããŒã¿åŠçãAPIåŒã³åºããªã©ãæ¥ã ã®äœæ¥ãèªååããã¡ãã£ãšããã¹ã¯ãªãããç°¡åã«ã³ãã³ãã©ã€ã³ãã䜿ããããã«ããŸãã
- ã©ã€ãã©ãªéçºæã®ãã¹ãã»ãããã°: éçºäžã®ã©ã€ãã©ãªã®ç¹å®ã®é¢æ°ãã¯ã©ã¹ã¡ãœãããã察話ã¢ãŒããªã©ã掻çšããŠçŽ æ©ãå®è¡ããåäœã確èªããŸãã
- å®éšç®¡ç: æ©æ¢°åŠç¿ã®å®éšãªã©ã§ããã€ããŒãã©ã¡ãŒã¿ãèšå®ãã³ãã³ãã©ã€ã³åŒæ°ã§æž¡ããç°ãªãèšå®ã§ã®å®è¡ã容æã«ããŸããGoogle Brainã§ãå®éšç®¡çããŒã«ã«å©çšãããŠããå®çžŸããããŸãã
- ç°¡åãªãããåŠç: å®æçã«å®è¡ããã¿ã¹ã¯ãªã©ããåŒæ°ãå€ããŠã³ãã³ãã©ã€ã³ããå®è¡ã§ããããã«ããŸãã
- æ¢åã³ãŒãã®CLIå: ä»ã®äººãæžããã³ãŒãããæ¢åã®ãããžã§ã¯ãã®äžéšæ©èœããã³ãŒãã倧ããå€æŽããããšãªãææ©ãCLIããŒã«ãšããŠå©çšã§ããããã«ããŸãã
- æè²ã»ãã¢ã³ã¹ãã¬ãŒã·ã§ã³: Pythonã®ã³ãŒããã©ã®ããã«åäœãããããã³ãã³ãã©ã€ã³ãã察話çã«ç€ºãã®ã«åœ¹ç«ã¡ãŸãã
äŸãã°ãç»ååŠçã©ã€ãã©ãªã䜿ã£ãŠãªãµã€ãºãè¡ãé¢æ°ãæžãããšããŸãã
# image_resizer.py
import fire
from PIL import Image # Pillowã©ã€ãã©ãªãå¿
èŠ pip install Pillow
import os
def resize_image(input_path, output_path, width, height):
"""ç»åããªãµã€ãºããŠä¿åããŸãã"""
try:
img = Image.open(input_path)
resized_img = img.resize((width, height))
# åºåãã£ã¬ã¯ããªãååšããªãå Žåã¯äœæ
os.makedirs(os.path.dirname(output_path), exist_ok=True)
resized_img.save(output_path)
print(f"Resized image saved to: {output_path}")
except FileNotFoundError:
print(f"Error: Input file not found at {input_path}")
except
ã³ã¡ã³ã