Python'da, içe aktarılan bir modülün main () 'ini çağırabilir miyim?


87

Python ben bir var modül Birkaç işlevleri ve tanımlamak myModule.py (ana) birkaç komut satırı argümanları alır.

Bunu genellikle bir bash betiğinden main () olarak adlandırırım. Şimdi, her şeyi küçük bir pakete koymak istiyorum , bu yüzden basit bash betiğimi bir Python betiğine çevirip pakete koyabileceğimi düşündüm.

Yani, nasıl ben aslında do ana () çağrısı myModule.py işlevini ana () işlevinden MyFormerBashScript.py ait? Ben bile yapabilir miyim? Ona nasıl argüman aktarırım ?


MyModule'ü içe aktardıysanız, arayabilmeniz gerekir myModule.main(). Şimdiye kadar ne denedin?
Marius

Genellikle bir kabuk betiğinden geçirdiğim girdi argümanlarından endişeleniyorum.
Ricky Robinson

subprocessModülle çağırmak mantıklı mı ?
BenDundee

Sanırım daha kolay olurdu, evet.
Ricky Robinson

Yanıtlar:


116

Bu sadece bir işlev. İçeri aktarın ve adlandırın:

import myModule

myModule.main()

Bağımsız değişkenleri çözümlemeniz gerekiyorsa, iki seçeneğiniz vardır:

  • Bunları ayrıştırın main(), ancak sys.argvbir parametre olarak iletin (aşağıdaki tüm kodlar aynı modülde myModule):

    def main(args):
        # parse arguments using optparse or argparse or what have you
    
    if __name__ == '__main__':
        import sys
        main(sys.argv[1:])
    

    Artık myModule.main(['arg1', 'arg2', 'arg3'])başka bir modülü içe aktarabilir ve başka bir modülden arayabilirsiniz .

  • Var main()zaten (yine tüm kodu işlendiğinden parametrelerini kabul myModulemodülü):

    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)
    

    ve myModule.main(foovalue, barvalue, baz='ham')başka bir yere içe aktarın ve çağırın ve gerektiğinde python argümanlarını iletin.

Buradaki püf noktası, modülünüzün komut dosyası olarak ne zaman kullanıldığını tespit etmektir; ana script ( python filename.py) olarak bir python dosyası çalıştırdığınızda hiçbir importifade kullanılmaz, bu nedenle python bu modülü çağırır "__main__". Ancak aynı filename.pykod bir module ( import filename) olarak değerlendirilirse, python bunu modül adı olarak kullanır. Her iki durumda da değişken __name__ayarlanır ve buna karşı test, kodunuzun nasıl çalıştırıldığını söyler.


3
Elbette. Peki ya girdi argümanları? Kullanıyorum argparse, bu yüzden komut dosyasını bir terminalden aradığımda ararım $ python myModule -a input_a -b input_b --parameterC input_c. Python kodunun içinden nasıl çalışır? Basit bir aramadan bulamadığım şey bu.
Ricky Robinson

@RickyRobinson: Her iki şekilde de sahip olabileceğinizi göstermek için genişletildi; sadece ayrıştırılan veya çözümlenecek bağımsız değişkenleri iletin.
Martijn Pieters

1
Teşekkürler. Ayrıca, hangi kod parçasının hangi modüle veya komut dosyasına ait olduğunu da belirtebilir misiniz? Başlangıçta düşündüğümden çok daha hantal görünüyor.
Ricky Robinson

@RickyRobinson: Her iki alıntı da aynı modüle ait; Bunu açık hale getirdim.
Martijn Pieters

42

Martijen'in cevabı mantıklı, ancak başkalarına açık gibi görünen ancak benim için çözmesi zor olan çok önemli bir şeyi gözden kaçırıyordu.

Argparse kullandığınız versiyonda, ana gövde içerisinde bu çizgiye sahip olmanız gerekmektedir.

args = parser.parse_args(args)

Normalde argparse'ı sadece bir komut dosyasında kullandığınızda

args = parser.parse_args()

ve parse_args komut satırındaki argümanları bulur. Ancak bu durumda ana işlevin komut satırı argümanlarına erişimi yoktur, bu nedenle argparse'a argümanların ne olduğunu söylemeniz gerekir.

İşte bir örnek

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:])

Bunu mytest.py olarak adlandırdığınızı varsayarsak, çalıştırmak için bunlardan herhangi birini komut satırından yapabilirsiniz

python ./mytest.py -x 8
python ./mytest.py -x 8 -y 2
python ./mytest.py 

sırasıyla dönen

X center: 8.0
Y center: 4

veya

X center: 8.0
Y center: 2.0

veya

X center: 2
Y center: 4

Veya başka bir python betiğinden çalıştırmak istiyorsanız şunları yapabilirsiniz:

import mytest
mytest.main(["-x","7","-y","6"]) 

hangi döner

X center: 7.0
Y center: 6.0

4
Bu tam olarak ihtiyacım olan
şeydi

Bu Python 2 ile çalışmış olabilir, ama Python 3'te bir modülün ana () işlev çağrısı olamaz, artık çalışmaz:AttributeError: module 'sqlacodegen' has no attribute 'main'
NaturalBornCamper

26

Değişir. Ana kod aşağıdaki gibi korunuyorsa if:

if __name__ == '__main__':
    ...main code...

o zaman hayır, Python'un bunu yürütmesini sağlayamazsınız çünkü otomatik değişkeni etkileyemezsiniz __name__.

Ancak tüm kod bir işlevde olduğunda, o zaman mümkün olabilir. Deneyin

import myModule

myModule.main()

Bu, modül kendisini bir __all__.

from myModule import *mainsize görünür hale gelmeyebilir, bu nedenle gerçekten modülün kendisini içe aktarmanız gerekir.


Tamam, açıklama için teşekkürler. Her şeyi bir main () işleve koyuyorum, bu yüzden tamam olmalı. Ben daha çok bu "ikinci" ana giriş argümanlarının nasıl geçirileceğiyle ilgileniyorum. Bunu yapmanın kolay bir yolu var mı?
Ricky Robinson

Elbette:import sys; module.main(sys.argv);
Aaron Digulla

Bu __main__bana yardımcı olan erişimle ilgili harika bir alternatif açıklama , teşekkürler @AaronDigulla
Charlie G

İşte başka bir işlevden ana çağırmanın bir püf noktası: stackoverflow.com/a/20158605/3244382
PatriceG

3

Ben de aynı ihtiyacım vardı argparse. Şey parse_argsbir işlevi argparse.ArgumentParsernesne örneği örtük varsayılan olarak kendi bağımsız değişkeni alır sys.args. Martijn çizgisini takip eden çalışma, bunu açık hale getirmekten ibarettir, böylece aktardığınız argümanları parse_argsarzu olarak değiştirebilirsiniz .

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:])

Kilit nokta, parse_argsişlevlere argümanlar iletmektir . Daha sonra ana kullanmak için Martijn'in dediği gibi yaparsınız.


3

Aradığım cevap burada cevaplandı: python argparse sys.argv dışındaki argümanlar ile nasıl kullanılır?

Eğer main.pyve parse_args()bu şekilde yazılır, sonra ayrıştırma güzel yapılabilir

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

Daha sonra main()argümanları parser.parse_args(['--input', 'foobar.txt'])başka bir python betiğinde çağırabilir ve ayrıştırabilirsiniz :

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

0

Komut satırı argümanlarını da iletmeye çalıştığınızı varsayarsak.

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:])

Teşekkürler. Aslında argparseyerine kullanıyorum sys.argv. Bu durumda nasıl değişirdi? Ayrıca, dış komut dosyasından, kullanıcının girdiği birkaç girdi argümanını iletmek istiyorum, oysa iç komut dosyası için diğer giriş argümanları (myModule.py) benim tarafımdan kodlanmıştır.
Ricky Robinson

Kodun kendisini görmeden ayrıntıları yanıtlamak zordur. Genel olarak, her türlü argümanı geçersiniz. *Unpacks bir dizi f(a) => f([1,2,3])vs f(*a) => f(1,2,3) You aynı kolaylıkla yapabileceği myModule.main(sys.argv[1], "other value", 39)ya da her neyse.
önce
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.