W Pythonie mam moduł myModule.py, w którym definiuję kilka funkcji oraz funkcję main () , która pobiera kilka argumentów wiersza poleceń.
Zwykle nazywam to main () ze skryptu bash. Teraz chciałbym umieścić wszystko w małym pakiecie , więc pomyślałem, że może mógłbym zamienić mój prosty skrypt bash na skrypt Pythona i umieścić go w pakiecie.
Jak więc właściwie wywołać funkcję main () myModule.py z funkcji main () MyFormerBashScript.py? Czy mogę to zrobić? Jak przekazać do niego jakiekolwiek argumenty ?
myModule.main()
. Czego spróbowałeś do tej pory?subprocess
modułem?Odpowiedzi:
To tylko funkcja. Zaimportuj i nazwij to:
import myModule myModule.main()
Jeśli potrzebujesz analizować argumenty, masz dwie możliwości:
Przetwórz je
main()
, ale przekażsys.argv
jako parametr (cały poniższy kod w tym samym modulemyModule
):def main(args): # parse arguments using optparse or argparse or what have you if __name__ == '__main__': import sys main(sys.argv[1:])
Teraz możesz importować i dzwonić
myModule.main(['arg1', 'arg2', 'arg3'])
z innego innego modułu.Mają
main()
akceptować parametry, które są już przeanalizowane (ponownie cały kod wmyModule
module):def main(foo, bar, baz='spam'): # run with already parsed arguments if __name__ == '__main__': import sys # parse sys.argv[1:] using optparse or argparse or what have you main(foovalue, barvalue, **dictofoptions)
importuj i wywołuj
myModule.main(foovalue, barvalue, baz='ham')
gdzie indziej i przekazuj argumenty Pythona w razie potrzeby.Sztuczka polega na tym, aby wykryć, kiedy twój moduł jest używany jako skrypt; kiedy uruchamiasz plik pythona jako główny skrypt (
python filename.py
), żadnaimport
instrukcja nie jest używana, więc python wywołuje ten moduł"__main__"
. Ale jeśli ten samfilename.py
kod jest traktowany jako module (import filename
), to python używa go jako nazwy modułu. W obu przypadkach zmienna__name__
jest ustawiona, a testowanie na jej podstawie powie Ci, jak Twój kod został uruchomiony.źródło
argparse
, więc kiedy wywołuję skrypt z terminala, robię$ python myModule -a input_a -b input_b --parameterC input_c
. Jak by to działało z poziomu kodu Pythona? Tego nie mogłem znaleźć w prostym wyszukiwaniu.Odpowiedź Martijena ma sens, ale brakowało w niej czegoś kluczowego, co może wydawać się oczywiste dla innych, ale było dla mnie trudne do zrozumienia.
W wersji, w której używasz argparse, musisz mieć tę linię w głównej części.
Zwykle, gdy używasz argparse tylko w skrypcie, po prostu piszesz
i parse_args znajdź argumenty z wiersza poleceń. Ale w tym przypadku główna funkcja nie ma dostępu do argumentów wiersza poleceń, więc musisz powiedzieć argparse, jakie to argumenty.
Oto przykład
import argparse import sys def x(x_center, y_center): print "X center:", x_center print "Y center:", y_center def main(args): parser = argparse.ArgumentParser(description="Do something.") parser.add_argument("-x", "--xcenter", type=float, default= 2, required=False) parser.add_argument("-y", "--ycenter", type=float, default= 4, required=False) args = parser.parse_args(args) x(args.xcenter, args.ycenter) if __name__ == '__main__': main(sys.argv[1:])
Zakładając, że nazwałeś ten mytest.py Aby go uruchomić, możesz wykonać dowolną z tych czynności z wiersza poleceń
python ./mytest.py -x 8 python ./mytest.py -x 8 -y 2 python ./mytest.py
który zwraca odpowiednio
X center: 8.0 Y center: 4
lub
X center: 8.0 Y center: 2.0
lub
X center: 2 Y center: 4
Lub jeśli chcesz uruchomić z innego skryptu Pythona, możesz to zrobić
import mytest mytest.main(["-x","7","-y","6"])
który powraca
X center: 7.0 Y center: 6.0
źródło
AttributeError: module 'sqlacodegen' has no attribute 'main'
To zależy. Jeśli główny kod jest chroniony przez
if
jak w:if __name__ == '__main__': ...main code...
to nie, nie możesz zmusić Pythona do wykonania tego, ponieważ nie możesz wpłynąć na zmienną automatyczną
__name__
.Ale jeśli cały kod znajduje się w funkcji, może to być możliwe. Próbować
import myModule myModule.main()
Działa to nawet wtedy, gdy moduł chroni się za pomocą pliku
__all__
.from myModule import *
może nie byćmain
widoczny dla Ciebie, więc naprawdę musisz zaimportować sam moduł.źródło
import sys; module.main(sys.argv);
__main__
które pomogło mi, dzięki @AaronDigullaMiałem tę samą potrzebę
argparse
. Chodzi o to, żeparse_args
funkcjaargparse.ArgumentParser
instancji obiektu domyślnie pobiera swoje argumenty zsys.args
. Obejście, zgodnie z linią Martijna, polega na wyraźnym wyrażeniu tego, abyś mógł zmienić argumenty, które przekazujeszparse_args
jako pożądanie.def main(args): # some stuff parser = argparse.ArgumentParser() # some other stuff parsed_args = parser.parse_args(args) # more stuff with the args if __name__ == '__main__': import sys main(sys.argv[1:])
Kluczową kwestią jest przekazywanie argumentów do
parse_args
funkcji. Później, aby skorzystać z głównego, po prostu postępuj zgodnie z instrukcjami Martijna.źródło
Odpowiedź, której szukałem, znalazła się tutaj: Jak używać argumentu Python z argumentami innymi niż sys.argv?
Jeśli
main.py
iparse_args()
jest napisane w ten sposób, to parsowanie można wykonać ładnie# main.py import argparse def parse_args(): parser = argparse.ArgumentParser(description="") parser.add_argument('--input', default='my_input.txt') return parser def main(args): print(args.input) if __name__ == "__main__": parser = parse_args() args = parser.parse_args() main(args)
Następnie możesz wywoływać
main()
i analizować argumentyparser.parse_args(['--input', 'foobar.txt'])
w innym skrypcie Pythona:# temp.py from main import main, parse_args parser = parse_args() args = parser.parse_args([]) # note the square bracket # to overwrite default, use parser.parse_args(['--input', 'foobar.txt']) print(args) # Namespace(input='my_input.txt') main(args)
źródło
Zakładając, że próbujesz przekazać również argumenty wiersza poleceń.
import sys import myModule def main(): # this will just pass all of the system arguments as is myModule.main(*sys.argv) # all the argv but the script name myModule.main(*sys.argv[1:])
źródło
argparse
zamiastsys.argv
. Jak by się to zmieniło w tym przypadku? Poza tym ze skryptu zewnętrznego chcę tylko przekazać kilka argumentów wejściowych, które wpisuje użytkownik, podczas gdy inne argumenty wejściowe dla skryptu wewnętrznego (myModule.py) są przeze mnie zakodowane na stałe.*
rozpakowuje tablicąf(a) => f([1,2,3])
vsf(*a) => f(1,2,3)
można było tak łatwo zrobić,myModule.main(sys.argv[1], "other value", 39)
czy cokolwiek innego.