Suche nach den Namen (und aufrufbaren Objekten) im aktuellen Skript __main__
Ich habe versucht, ein eigenständiges Python-Skript zu erstellen, das nur die Standardbibliothek verwendet, um Funktionen in der aktuellen Datei mit dem Präfix task_
um eine minimale selbstgebaute Version dessen zu erstellen, was npm run
bietet.
TL;DR
Wenn Sie ein eigenständiges Skript ausführen, müssen Sie inspect.getmembers
über die module
die definiert ist in sys.modules['__main__']
. Beispiel,
inspect.getmembers(sys.modules['__main__'], inspect.isfunction)
Aber ich wollte die Liste der Methoden nach Präfix filtern und das Präfix entfernen, um ein Nachschlagewörterbuch zu erstellen.
def _inspect_tasks():
import inspect
return { f[0].replace('task_', ''): f[1]
for f in inspect.getmembers(sys.modules['__main__'], inspect.isfunction)
if f[0].startswith('task_')
}
Beispiel Ausgabe:
{
'install': <function task_install at 0x105695940>,
'dev': <function task_dev at 0x105695b80>,
'test': <function task_test at 0x105695af0>
}
Längere Version
Ich wollte, dass die Namen der Methoden die Namen der CLI-Aufgaben definieren, ohne mich wiederholen zu müssen.
./tasks.py
#!/usr/bin/env python3
import sys
from subprocess import run
def _inspect_tasks():
import inspect
return { f[0].replace('task_', ''): f[1]
for f in inspect.getmembers(sys.modules['__main__'], inspect.isfunction)
if f[0].startswith('task_')
}
def _cmd(command, args):
return run(command.split(" ") + args)
def task_install(args):
return _cmd("python3 -m pip install -r requirements.txt -r requirements-dev.txt --upgrade", args)
def task_test(args):
return _cmd("python3 -m pytest", args)
def task_dev(args):
return _cmd("uvicorn api.v1:app", args)
if __name__ == "__main__":
tasks = _inspect_tasks()
if len(sys.argv) >= 2 and sys.argv[1] in tasks.keys():
tasks[sys.argv[1]](sys.argv[2:])
else:
print(f"Must provide a task from the following: {list(tasks.keys())}")
Beispiel ohne Argumente:
./tasks.py
Must provide a task from the following: ['install', 'dev', 'test']
Beispiel für einen Test mit zusätzlichen Argumenten:
./tasks.py test -qq
s.ssss.sF..Fs.sssFsss..ssssFssFs....s.s
Sie wissen, worum es geht. Da meine Projekte immer umfangreicher werden, wird es einfacher sein, ein Skript auf dem neuesten Stand zu halten, als die README auf dem neuesten Stand zu halten, und ich kann es auf das Wesentliche reduzieren:
./tasks.py install
./tasks.py dev
./tasks.py test
./tasks.py publish
./tasks.py logs