Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
270 views
in Technique[技术] by (71.8m points)

python - __name__ ==“ __main__”怎么办?(What does if __name__ == “__main__”: do?)

What does the if __name__ == "__main__": do?

(if __name__ == "__main__":什么作用?)

# Threading example
import time, thread

def myfunction(string, sleeptime, lock, *args):
    while True:
        lock.acquire()
        time.sleep(sleeptime)
        lock.release()
        time.sleep(sleeptime)

if __name__ == "__main__":
    lock = thread.allocate_lock()
    thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
    thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
  ask by Devoted translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Whenever the Python interpreter reads a source file, it does two things:

(每当Python解释器读取源文件时,它都会做两件事:)

  • it sets a few special variables like __name__ , and then

    (它设置了一些特殊变量,例如__name__ ,然后)

  • it executes all of the code found in the file.

    (它执行文件中找到的所有代码。)

Let's see how this works and how it relates to your question about the __name__ checks we always see in Python scripts.

(让我们看看它是如何工作的,以及它与您在Python脚本中经常看到的有关__name__检查的问题之间的__name__ 。)

Code Sample (代码样例)

Let's use a slightly different code sample to explore how imports and scripts work.

(让我们使用稍微不同的代码示例来探索导入和脚本的工作方式。)

Suppose the following is in a file called foo.py .

(假设以下内容位于名为foo.py的文件中。)

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

Special Variables (特殊变量)

When the Python interpeter reads a source file, it first defines a few special variables.

(当Python交互程序读取源文件时,它首先定义一些特殊变量。)

In this case, we care about the __name__ variable.

(在这种情况下,我们关心的是__name__变量。)

When Your Module Is the Main Program

(当您的模块是主程序时)

If you are running your module (the source file) as the main program, eg

(如果您将模块(源文件)作为主程序运行,例如)

python foo.py

the interpreter will assign the hard-coded string "__main__" to the __name__ variable, ie

(解释器将硬编码字符串"__main__"分配给__name__变量,即)

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

When Your Module Is Imported By Another

(当您的模块由另一个导入时)

On the other hand, suppose some other module is the main program and it imports your module.

(另一方面,假设其他模块是主程序,并且它将导入您的模块。)

This means there's a statement like this in the main program, or in some other module the main program imports:

(这意味着在主程序中或主程序导入的某些其他模块中有这样的语句:)

# Suppose this is in some other main program.
import foo

In this case, the interpreter will look at the filename of your module, foo.py , strip off the .py , and assign that string to your module's __name__ variable, ie

(在这种情况下,解释器将查看模块的文件名foo.py ,剥离.py ,然后将该字符串分配给模块的__name__变量,即)

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Executing the Module's Code (执行模块的代码)

After the special variables are set up, the interpreter executes all the code in the module, one statement at a time.

(设置特殊变量后,解释器一次执行一个语句,执行模块中的所有代码。)

You may want to open another window on the side with the code sample so you can follow along with this explanation.

(您可能想要在代码示例侧面打开另一个窗口,以便您可以按照以下说明进行操作。)

Always

(总是)

  1. It prints the string "before import" (without quotes).

    (它输出字符串"before import" (不带引号)。)

  2. It loads the math module and assigns it to a variable called math .

    (它加载math模块并将其分配给名为math的变量。)

    This is equivalent to replacing import math with the following (note that __import__ is a low-level function in Python that takes a string and triggers the actual import):

    (这等效于将import math替换为以下内容(请注意, __import__是Python中的低级函数,它接受字符串并触发实际的导入):)

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. It prints the string "before functionA" .

    (它打印字符串"before functionA" 。)

  2. It executes the def block, creating a function object, then assigning that function object to a variable called functionA .

    (它执行def块,创建一个功能对象,然后将该功能对象分配给一个名为functionA的变量。)

  3. It prints the string "before functionB" .

    (它输出字符串"before functionB" 。)

  4. It executes the second def block, creating another function object, then assigning it to a variable called functionB .

    (它执行第二个def块,创建另一个功能对象,然后将其分配给名为functionB的变量。)

  5. It prints the string "before __name__ guard" .

    (它输出字符串"before __name__ guard" 。)

Only When Your Module Is the Main Program

(仅当您的模块是主程序时)

  1. If your module is the main program, then it will see that __name__ was indeed set to "__main__" and it calls the two functions, printing the strings "Function A" and "Function B 10.0" .

    (如果您的模块是主程序,那么它将看到__name__确实设置为"__main__"并且它将调用两个函数,分别打印字符串"Function A""Function B 10.0" 。)

Only When Your Module Is Imported by Another

(仅当您的模块由另一个导入时)

  1. ( instead ) If your module is not the main program but was imported by another one, then __name__ will be "foo" , not "__main__" , and it'll skip the body of the if statement.

    (( 相反 )如果您的模块不是主程序而是由另一个程序导入的,则__name__将为"foo" ,而不是"__main__" ,它将跳过if语句的主体。)

Always

(总是)

  1. It will print the string "after __name__ guard" in both situations.

    (在两种情况下,它将在"after __name__ guard"打印字符串。)

Summary

(摘要)

In summary, here's what'd be printed in the two cases:

(总而言之,这是两种情况下的打印内容:)

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

Why Does It Work This Way? (为什么这样工作?)

You might naturally wonder why anybody would want this.

(您自然会想知道为什么有人会想要这个。)

Well, sometimes you want to write a .py file that can be both used by other programs and/or modules as a module, and can also be run as the main program itself.

(好吧,有时候您想编写一个.py文件,该文件既可以供其他程序和/或模块用作模块,又可以作为主程序本身运行。)

Examples:

(例子:)

  • Your module is a library, but you want to have a script mode where it runs some unit tests or a demo.

    (您的模块是一个库,但是您希望有一个脚本模式,在其中运行一些单元测试或演示。)

  • Your module is only used as a main program, but it has some unit tests, and the testing framework works by importing .py files like your script and running special test functions.

    (您的模块仅用作主程序,但具有一些单元测试,并且测试框架通过导入.py文件(如脚本)并运行特殊的测试功能来工作。)

    You don't want it to try running the script just because it's importing the module.

    (您不希望它只是因为正在导入模块而尝试运行脚本。)

  • Your module is mostly used as a main program, but it also provides a programmer-friendly API for advanced users.

    (您的模块主要用作主程序,但它也为高级用户提供了程序员友好的API。)

Beyond those examples, it's elegant that running a script in Python is just setting up a few magic variables and importing the script.

(除了这些示例之外,可以优雅地用Python运行脚本只是设置一些魔术变量并导入脚本。)

"Running" the script is a side effect of importing the script's module.

(“运行”脚本是导入脚本模块的副作用。)

Food for Thought (思想的食物)

  • Question: Can I have multiple __name__ checking blocks?

    (问题:我可以有多个__name__检查块吗?)

    Answer: it's strange to do so, but the language won't stop you.

    (答:这样做很奇怪,但是这种语言不会阻止您。)

  • Suppose the following is in foo2.py .

    (假设以下内容在foo2.py 。)

    What happens if you say python foo2.py on the command-line?

    (如果在命令行上说python foo2.py会发生什么?)

    Why?

    (为什么?)

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • Now, figure out what will happen if you remove the __name__ check in foo3.py :

    (现在,如果你删除弄明白会发生什么__name__在检查foo3.py :)

# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • What will this do when used as a script?

    (当用作脚本时,它将做什么?)

    When imported as a module?

    (当作为模块导入时?)

# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...