__main__ — Top-level code environment — Python 3.10 ...

文章推薦指數: 80 %
投票人數:10人

__main__ is the name of the environment where top-level code is run. “Top-level code” is the first user-specified Python module that starts running. Navigation index modules| next| previous| Python» 3.10.7Documentation» ThePythonStandardLibrary» PythonRuntimeServices» __main__—Top-levelcodeenvironment | __main__—Top-levelcodeenvironment¶ InPython,thespecialname__main__isusedfortwoimportantconstructs: thenameofthetop-levelenvironmentoftheprogram,whichcanbe checkedusingthe__name__=='__main__'expression;and the__main__.pyfileinPythonpackages. BothofthesemechanismsarerelatedtoPythonmodules;howusersinteractwith themandhowtheyinteractwitheachother.Theyareexplainedindetail below.Ifyou’renewtoPythonmodules,seethetutorialsection Modulesforanintroduction. __name__=='__main__'¶ WhenaPythonmoduleorpackageisimported,__name__issettothe module’sname.Usually,thisisthenameofthePythonfileitselfwithoutthe .pyextension: >>>importconfigparser >>>configparser.__name__ 'configparser' Ifthefileispartofapackage,__name__willalsoincludetheparent package’spath: >>>fromconcurrent.futuresimportprocess >>>process.__name__ 'concurrent.futures.process' However,ifthemoduleisexecutedinthetop-levelcodeenvironment, its__name__issettothestring'__main__'. Whatisthe“top-levelcodeenvironment”?¶ __main__isthenameoftheenvironmentwheretop-levelcodeisrun. “Top-levelcode”isthefirstuser-specifiedPythonmodulethatstartsrunning. It’s“top-level”becauseitimportsallothermodulesthattheprogramneeds. Sometimes“top-levelcode”iscalledanentrypointtotheapplication. Thetop-levelcodeenvironmentcanbe: thescopeofaninteractiveprompt: >>>__name__ '__main__' thePythonmodulepassedtothePythoninterpreterasafileargument: $python3helloworld.py Hello,world! thePythonmoduleorpackagepassedtothePythoninterpreterwiththe -margument: $python3-mtarfile usage:tarfile.py[-h][-v](...) PythoncodereadbythePythoninterpreterfromstandardinput: $echo"importthis"|python3 TheZenofPython,byTimPeters Beautifulisbetterthanugly. Explicitisbetterthanimplicit. ... PythoncodepassedtothePythoninterpreterwiththe-cargument: $python3-c"importthis" TheZenofPython,byTimPeters Beautifulisbetterthanugly. Explicitisbetterthanimplicit. ... Ineachofthesesituations,thetop-levelmodule’s__name__issetto '__main__'. Asaresult,amodulecandiscoverwhetherornotitisrunninginthe top-levelenvironmentbycheckingitsown__name__,whichallowsacommon idiomforconditionallyexecutingcodewhenthemoduleisnotinitializedfrom animportstatement: if__name__=='__main__': #Executewhenthemoduleisnotinitializedfromanimportstatement. ... Seealso Foramoredetailedlookathow__name__issetinallsituations,see thetutorialsectionModules. IdiomaticUsage¶ Somemodulescontaincodethatisintendedforscriptuseonly,likeparsing command-lineargumentsorfetchingdatafromstandardinput.Ifamodule likethiswasimportedfromadifferentmodule,forexampletounittest it,thescriptcodewouldunintentionallyexecuteaswell. Thisiswhereusingtheif__name__=='__main__'codeblockcomesin handy.Codewithinthisblockwon’trununlessthemoduleisexecutedinthe top-levelenvironment. Puttingasfewstatementsaspossibleintheblockbelowif__name___== '__main__'canimprovecodeclarityandcorrectness.Mostoften,afunction namedmainencapsulatestheprogram’sprimarybehavior: #echo.py importshlex importsys defecho(phrase:str)->None: """Adummywrapperaroundprint.""" #fordemonstrationpurposes,youcanimaginethatthereissome #valuableandreusablelogicinsidethisfunction print(phrase) defmain()->int: """Echotheinputargumentstostandardoutput""" phrase=shlex.join(sys.argv) echo(phrase) return0 if__name__=='__main__': sys.exit(main())#nextsectionexplainstheuseofsys.exit Notethatifthemoduledidn’tencapsulatecodeinsidethemainfunction butinsteadputitdirectlywithintheif__name__=='__main__'block, thephrasevariablewouldbeglobaltotheentiremodule.Thisis error-proneasotherfunctionswithinthemodulecouldbeunintentionallyusing theglobalvariableinsteadofalocalname.Amainfunctionsolvesthis problem. Usingamainfunctionhastheaddedbenefitoftheechofunctionitself beingisolatedandimportableelsewhere.Whenecho.pyisimported,the echoandmainfunctionswillbedefined,butneitherofthemwillbe called,because__name__!='__main__'. PackagingConsiderations¶ mainfunctionsareoftenusedtocreatecommand-linetoolsbyspecifying themasentrypointsforconsolescripts.Whenthisisdone, pipinsertsthefunctioncallintoatemplatescript, wherethereturnvalueofmainispassedintosys.exit(). Forexample: sys.exit(main()) Sincethecalltomainiswrappedinsys.exit(),theexpectationis thatyourfunctionwillreturnsomevalueacceptableasaninputto sys.exit();typically,anintegerorNone(whichisimplicitly returnedifyourfunctiondoesnothaveareturnstatement). Byproactivelyfollowingthisconventionourselves,ourmodulewillhavethe samebehaviorwhenrundirectly(i.e.python3echo.py)asitwillhaveif welaterpackageitasaconsolescriptentry-pointinapip-installable package. Inparticular,becarefulaboutreturningstringsfromyourmainfunction. sys.exit()willinterpretastringargumentasafailuremessage,so yourprogramwillhaveanexitcodeof1,indicatingfailure,andthe stringwillbewrittentosys.stderr.Theecho.pyexamplefrom earlierexemplifiesusingthesys.exit(main())convention. Seealso PythonPackagingUserGuide containsacollectionoftutorialsandreferencesonhowtodistributeand installPythonpackageswithmoderntools. __main__.pyinPythonPackages¶ IfyouarenotfamiliarwithPythonpackages,seesectionPackages ofthetutorial.Mostcommonly,the__main__.pyfileisusedtoprovide acommand-lineinterfaceforapackage.Considerthefollowinghypothetical package,“bandclass”: bandclass ├──__init__.py ├──__main__.py └──student.py __main__.pywillbeexecutedwhenthepackageitselfisinvoked directlyfromthecommandlineusingthe-mflag.Forexample: $python3-mbandclass Thiscommandwillcause__main__.pytorun.Howyouutilizethismechanism willdependonthenatureofthepackageyouarewriting,butinthis hypotheticalcase,itmightmakesensetoallowtheteachertosearchfor students: #bandclass/__main__.py importsys from.studentimportsearch_students student_name=sys.argv[2]iflen(sys.argv)>=2else'' print(f'Foundstudent:{search_students(student_name)}') Notethatfrom.studentimportsearch_studentsisanexampleofarelative import.Thisimportstylecanbeusedwhenreferencingmoduleswithina package.Formoredetails,seeIntra-packageReferencesinthe Modulessectionofthetutorial. IdiomaticUsage¶ Thecontentsof__main__.pytypicallyisn’tfencedwith if__name__=='__main__'blocks.Instead,thosefilesarekeptshort, functionstoexecutefromothermodules.Thoseothermodulescanthenbe easilyunit-testedandareproperlyreusable. Ifused,anif__name__=='__main__'blockwillstillworkasexpected fora__main__.pyfilewithinapackage,becauseits__name__ attributewillincludethepackage’spathifimported: >>>importasyncio.__main__ >>>asyncio.__main__.__name__ 'asyncio.__main__' Thiswon’tworkfor__main__.pyfilesintherootdirectoryofa.zipfile though.Hence,forconsistency,minimal__main__.pylikethevenv onementionedbelowarepreferred. Seealso Seevenvforanexampleofapackagewithaminimal__main__.py inthestandardlibrary.Itdoesn’tcontainaif__name__=='__main__' block.Youcaninvokeitwithpython3-mvenv[directory]. Seerunpyformoredetailsonthe-mflagtothe interpreterexecutable. Seezipappforhowtorunapplicationspackagedas.zipfiles.In thiscasePythonlooksfora__main__.pyfileintherootdirectoryof thearchive. import__main__¶ RegardlessofwhichmoduleaPythonprogramwasstartedwith,othermodules runningwithinthatsameprogramcanimportthetop-levelenvironment’sscope (namespace)byimportingthe__main__module.Thisdoesn’timport a__main__.pyfilebutratherwhichevermodulethatreceivedthespecial name'__main__'. Hereisanexamplemodulethatconsumesthe__main__namespace: #namely.py import__main__ defdid_user_define_their_name(): return'my_name'indir(__main__) defprint_user_name(): ifnotdid_user_define_their_name(): raiseValueError('Definethevariable`my_name`!') if'__file__'indir(__main__): print(__main__.my_name,"foundinfile",__main__.__file__) else: print(__main__.my_name) Exampleusageofthismodulecouldbeasfollows: #start.py importsys fromnamelyimportprint_user_name #my_name="Dinsdale" defmain(): try: print_user_name() exceptValueErrorasve: returnstr(ve) if__name__=="__main__": sys.exit(main()) Now,ifwestartedourprogram,theresultwouldlooklikethis: $python3start.py Definethevariable`my_name`! Theexitcodeoftheprogramwouldbe1,indicatinganerror.Uncommentingthe linewithmy_name="Dinsdale"fixestheprogramandnowitexitswith statuscode0,indicatingsuccess: $python3start.py Dinsdalefoundinfile/path/to/start.py Notethatimporting__main__doesn’tcauseanyissueswithunintentionally runningtop-levelcodemeantforscriptusewhichisputinthe if__name__=="__main__"blockofthestartmodule.Whydoesthiswork? Pythoninsertsanempty__main__moduleinsys.modulesat interpreterstartup,andpopulatesitbyrunningtop-levelcode.Inourexample thisisthestartmodulewhichrunslinebylineandimportsnamely. Inturn,namelyimports__main__(whichisreallystart).That’san importcycle!Fortunately,sincethepartiallypopulated__main__ moduleispresentinsys.modules,Pythonpassesthattonamely. SeeSpecialconsiderationsfor__main__inthe importsystem’sreferencefordetailsonhowthisworks. ThePythonREPLisanotherexampleofa“top-levelenvironment”,soanything definedintheREPLbecomespartofthe__main__scope: >>>importnamely >>>namely.did_user_define_their_name() False >>>namely.print_user_name() Traceback(mostrecentcalllast): ... ValueError:Definethevariable`my_name`! >>>my_name='Jabberwocky' >>>namely.did_user_define_their_name() True >>>namely.print_user_name() Jabberwocky Notethatinthiscasethe__main__scopedoesn’tcontaina__file__ attributeasit’sinteractive. The__main__scopeisusedintheimplementationofpdband rlcompleter. TableofContents __main__—Top-levelcodeenvironment __name__=='__main__' Whatisthe“top-levelcodeenvironment”? IdiomaticUsage PackagingConsiderations __main__.pyinPythonPackages IdiomaticUsage import__main__ Previoustopic builtins—Built-inobjects Nexttopic warnings—Warningcontrol ThisPage ReportaBug ShowSource Navigation index modules| next| previous| Python» 3.10.7Documentation» ThePythonStandardLibrary» PythonRuntimeServices» __main__—Top-levelcodeenvironment |



請為這篇文章評分?