पायथन में, क्या मैं एक आयातित मॉड्यूल के मुख्य () को कॉल कर सकता हूं?


86

पायथन में मेरे पास एक मॉड्यूल myModule.py है जहां मैं कुछ फ़ंक्शन और एक मुख्य () को परिभाषित करता हूं , जो कुछ कमांड कमांड तर्क लेता है।

मैं आमतौर पर एक बैश स्क्रिप्ट से इस मुख्य () को कॉल करता हूं। अब, मैं सब कुछ एक छोटे पैकेज में रखना चाहूंगा , इसलिए मैंने सोचा कि शायद मैं अपनी साधारण बैश स्क्रिप्ट को पायथन स्क्रिप्ट में बदल सकता हूं और इसे पैकेज में डाल सकता हूं।

तो, कैसे मैं वास्तव में है मुख्य () फोन myModule.py का कार्य मुख्य () फ़ंक्शन से MyFormerBashScript.py की? क्या मैं भी ऐसा कर सकता हूं? मैं इसके लिए कोई तर्क कैसे पारित करूं ?


यदि आपने myModule आयात किया है, तो आपको कॉल करने में सक्षम होना चाहिए myModule.main()। अब तक तुमने क्या प्रयास किये हैं?
मारीस

मैं इनपुट तर्कों से चिंतित हूं, जो मैं आमतौर पर एक शेल स्क्रिप्ट से गुजरता हूं।
रिकी रॉबिन्सन

क्या यह subprocessमॉड्यूल के साथ कॉल करने के लिए समझ में आता है ?
बेनडुंडी

मुझे लगता है कि यह आसान होगा, हाँ।
रिकी रॉबिन्सन

जवाबों:


114

यह सिर्फ एक समारोह है। इसे आयात करें और इसे कॉल करें:

import myModule

myModule.main()

यदि आपको तर्कों को पार्स करने की आवश्यकता है, तो आपके पास दो विकल्प हैं:

  • उन्हें पार्स करें main(), लेकिन sys.argvएक पैरामीटर के रूप में पास करें (सभी कोड नीचे एक ही मॉड्यूल में myModule):

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

    अब आप myModule.main(['arg1', 'arg2', 'arg3'])दूसरे मॉड्यूल से आयात और कॉल कर सकते हैं ।

  • उन main()मापदंडों को स्वीकार करें जो पहले से ही पार्स हैं (फिर से myModuleमॉड्यूल में सभी कोड ):

    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)
    

    और आयात और कॉल myModule.main(foovalue, barvalue, baz='ham')कहीं और जरूरत के अनुसार अजगर तर्कों में गुजर रहा है।

यहां ट्रिक यह पता लगाना है कि आपके मॉड्यूल को स्क्रिप्ट के रूप में कब इस्तेमाल किया जा रहा है; जब आप एक अजगर फ़ाइल को मुख्य स्क्रिप्ट के रूप में चलाते हैं ( python filename.py) कोई importकथन का उपयोग नहीं किया जा रहा है, तो अजगर उस मॉड्यूल को कॉल करता है "__main__"। लेकिन अगर उसी filename.pyकोड को एक मॉड्यूल ( import filename) के रूप में माना जाता है , तो अजगर उस के बजाय मॉड्यूल नाम के रूप में उपयोग करता है। दोनों मामलों में चर __name__सेट है, और इसके खिलाफ परीक्षण आपको बताता है कि आपका कोड कैसे चलाया गया था।


3
ज़रूर। लेकिन इनपुट तर्कों का क्या? मैं उपयोग करता हूं argparse, इसलिए जब मैं एक टर्मिनल से स्क्रिप्ट को कॉल करता हूं, तो मैं करता हूं $ python myModule -a input_a -b input_b --parameterC input_c। यह अजगर कोड के भीतर से कैसे काम करेगा? यही कारण है कि मैं एक साधारण खोज से नहीं मिल सकता है।
रिकी रॉबिन्सन

@ रिकी रॉबिन्सन: यह दिखाने के लिए विस्तारित किया गया है कि आपके पास इसके दोनों तरीके हो सकते हैं; पार्स किए गए या पार्स किए गए तर्कों में बस पास हो जाएं।
मार्टिन पीटर्स

1
धन्यवाद। क्या आप यह भी बता सकते हैं कि कोड का कौन सा अंश किस मॉड्यूल या स्क्रिप्ट से संबंधित है? यह शुरुआत में जितना मैंने सोचा था उससे कहीं अधिक बोझिल लग रहा है।
रिकी रॉबिन्सन

@RickyRobinson: दोनों अंश एक ही मॉड्यूल में एक साथ हैं; मैंने स्पष्ट किया है।
मार्टिन पीटर्स

42

मार्टिज़न का जवाब समझ में आता है, लेकिन यह कुछ महत्वपूर्ण याद आ रहा था जो दूसरों के लिए स्पष्ट लग सकता है लेकिन मेरे लिए यह पता लगाना कठिन था।

उस संस्करण में जहां आप argparse का उपयोग करते हैं, आपको मुख्य बॉडी में इस लाइन का होना आवश्यक है।

args = parser.parse_args(args)

आम तौर पर जब आप सिर्फ एक स्क्रिप्ट में अर्गपर्स का उपयोग कर रहे होते हैं, जिसे आप लिखते हैं

args = parser.parse_args()

और parse_args कमांड लाइन से तर्क ढूंढते हैं। लेकिन इस मामले में मुख्य फ़ंक्शन के पास कमांड लाइन के तर्कों तक पहुंच नहीं है, इसलिए आपको यह बताना होगा कि तर्क क्या हैं।

यहाँ एक उदाहरण है

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

यह मानते हुए कि आपने mytest.py नाम दिया है इसे चलाने के लिए आप कमांड लाइन से इनमें से कोई भी कर सकते हैं

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

जो क्रमशः लौटता है

X center: 8.0
Y center: 4

या

X center: 8.0
Y center: 2.0

या

X center: 2
Y center: 4

या यदि आप एक और अजगर स्क्रिप्ट से भागना चाहते हैं तो आप कर सकते हैं

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

जो लौटता है

X center: 7.0
Y center: 6.0

4
यह वही है जो मुझे चाहिए था - मददगार परिशिष्ट के लिए बहुत बहुत धन्यवाद
HFBrowning

यह पायथन 2 के साथ काम कर सकता है, लेकिन पायथन 3 में यह अब काम नहीं करता है, एक मॉड्यूल के मुख्य () फ़ंक्शन को कॉल नहीं कर सकता:AttributeError: module 'sqlacodegen' has no attribute 'main'
प्राकृतिकबॉर्नकेपर

24

निर्भर करता है। यदि मुख्य कोड निम्नानुसार संरक्षित है if:

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

तब नहीं, आप पायथन को निष्पादित नहीं कर सकते हैं क्योंकि आप स्वचालित चर को प्रभावित नहीं कर सकते हैं __name__

लेकिन जब सभी कोड किसी फ़ंक्शन में होते हैं, तो हो सकता है। प्रयत्न

import myModule

myModule.main()

यह तब भी काम करता है जब मॉड्यूल खुद की सुरक्षा करता है __all__

from myModule import *हो सकता है कि mainआपको दिखाई न दे, इसलिए आपको वास्तव में मॉड्यूल को स्वयं आयात करना होगा।


ओह ठीक है, स्पष्टीकरण के लिए धन्यवाद। मैंने सब कुछ एक मुख्य () फ़ंक्शन में रखा, इसलिए यह ठीक होना चाहिए। मैं इस बारे में अधिक चिंतित हूं कि इस "मुख्य" इनपुट तर्कों को कैसे पारित किया जाए। ऐसा करने का कोई आसान तरीका?
रिकी रॉबिन्सन

ज़रूर:import sys; module.main(sys.argv);
हारून दिगुल्ला

यह एक्सेस करने के बारे में एक शानदार वैकल्पिक व्याख्या है __main__जिसने मुझे मदद की, धन्यवाद @AaronDigulla
चार्ली जी

एक अन्य समारोह से मुख्य कॉल करने के लिए यहां एक चाल है: stackoverflow.com/a/20158605/3244382
PatriceG

3

मुझे भी इसी तरह की ज़रूरत argparseथी। यह वस्तु parse_argsएक argparse.ArgumentParserवस्तु उदाहरण का कार्य है, जो मूल रूप से डिफ़ॉल्ट रूप से अपने तर्क लेती है sys.args। मार्टिज्न लाइन के बाद के काम के बारे में बताया गया है कि यह स्पष्ट है, इसलिए आप उन तर्कों को बदल सकते हैं जिन्हें आप parse_argsइच्छा के रूप में पास करते हैं ।

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

कुंजी बिंदु parse_argsकार्य करने के लिए args गुजर रहा है । बाद में, मुख्य का उपयोग करने के लिए, आप सिर्फ मार्टिज़न को बताते हैं।


3

मैं जिस उत्तर की खोज कर रहा था, उसका उत्तर यहाँ दिया गया था: sys.argv के अलावा अन्य आर्ग्स के साथ अजगर argparse का उपयोग कैसे करें?

तो main.pyऔर parse_args()इस तरह से लिखा है, तो पार्स अच्छी तरह से किया जा सकता है

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

तब आप किसी अन्य अजगर लिपि में इसके main()साथ तर्कों को कॉल और पार्स कर सकते हैं parser.parse_args(['--input', 'foobar.txt']):

# 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

मान लें कि आप कमांड लाइन के तर्कों को भी पारित करना चाहते हैं।

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

धन्यवाद। मैं वास्तव में के argparseबजाय का उपयोग कर रहा हूँ sys.argv। इस मामले में यह कैसे बदलेगा? इसके अलावा, बाहरी स्क्रिप्ट से मैं केवल उपयोगकर्ता प्रकारों में कुछ इनपुट तर्कों को पारित करना चाहता हूं, जबकि आंतरिक स्क्रिप्ट (myModule.py) के लिए अन्य इनपुट तर्क मेरे द्वारा हार्डकोड किए गए हैं।
रिकी रॉबिन्सन

कोड देखे बिना ही बारीकियों का जवाब देना कठिन है। सामान्य तौर पर, आप बस जो भी तर्क देते हैं, पारित करेंगे। *Unpacks एक सरणी f(a) => f([1,2,3])बनाम f(*a) => f(1,2,3) तुम बस के रूप में आसानी से कर सकता myModule.main(sys.argv[1], "other value", 39)या जो कुछ भी।
वेबेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.