La entrada del programa Python __name__ == '__main__' tiene funciones importantes (multi-threading) en lugar de hábitos de programación

El artículo proviene de Internet (https://jq.qq.com/?_wv=1027&k=rX9CWKg4)

En Python, el if name == ' main ': llamado "entrada de programa" : siempre aparece en varios códigos de muestra, y existe una idea errónea generalizada de que "es solo un idioma de codificación en Python". De hecho, la entrada del programa es muy útil y de ninguna manera es opcional.Por ejemplo, la biblioteca de subprocesos múltiples que viene con Python requiere que el proceso principal se escriba dentro de la entrada if para ejecutarse normalmente.

El código escrito directamente en el extremo izquierdo de Python sin sangría se ejecutará cuando el archivo *.py se ejecute directamente o se llame, solo si está escrito en if name == ' main ': dentro de la entrada if no se llamará cuando se ejecute. Python usa este método simple para determinar si el módulo actual se ejecuta o llama directamente, lo cual es una función muy importante, como:

  • Podemos poner código que no queremos que se ejecute cuando se llame dentro del if dentro de la entrada del programa, como un programa de autoprueba.
  • También escribimos el hilo principal multiproceso dentro del if de la entrada del programa. Solo puede hacer esto para evitar repetir la ejecución del proceso principal cuando se llama a sí mismo, lo cual se explicará en detalle a continuación.

Por lo tanto, cuando aprenda Python por primera vez, escriba el programa principal directamente en una posición que no requiera sangría, y no escriba if name ==' main ' en absoluto: por supuesto. Un novato que no tiene la capacidad de escribir una biblioteca para llamar, ni necesariamente tiene que aprender multiprocesamiento, puede pensar erróneamente que "el punto de entrada del programa" es inútil.

Del mismo modo, algunas personas malinterpretan los encabezados de los archivos de Python:

#!/bin/bash/python3  # 这一句话用来在代码被执行时,主动说明该选哪个路径下的编译器
#!/bin/bash/python2  # 例如这一句就选了Python2,不过2020年Python2快要完成过渡使命了

A finales de 2020, cuando estaba escribiendo un tutorial multiproceso de Python, no busqué un artículo adecuado que explicara "la entrada del programa if name == ' main ': la conexión necesaria con subprocesos múltiples", pero Vi muchas respuestas unilaterales de grandes elogios. Desesperado, tuve que escribirlo yo mismo. Para algunas personas con conocimientos básicos, también vale la pena echarle un vistazo a la siguiente sección sobre entrada de programas y subprocesos múltiples.

contenido

  • ¿Qué es la "entrada al programa"?
  • Entrada de programa y programa de autocomprobación
  • Entrada de programa y subprocesamiento múltiple

registro de cambios

  • La primera edición 2021-01-01 Actualizaré las buenas preguntas en el área de comentarios al texto.

¿Qué es la "entrada al programa"?

Se puede explicar en palabras muy cortas. Estoy de acuerdo con la respuesta del análisis de novatos↓. Algunas de las respuestas de grandes elogios están escritas de manera prolija.

name es el nombre del módulo actual, que se llama main cuando el módulo se ejecuta directamente . El significado de esta oración es que cuando el módulo se ejecuta directamente, se ejecutará el siguiente bloque de código, cuando se importa el módulo, el bloque de código no se ejecutará.

Por ejemplo: cuando ejecuto python3 run1.py directamente en la terminal, el nombre del módulo siempre se cambia a la cadena __main__, cuando el módulo es importado por otro programa *.py (como import run1 en *.py) en lugar de directamente En tiempo de ejecución, el nombre del módulo es la cadena run1.

Hay "puntos de entrada del programa" similares en lenguaje C y Java:


# Python的程序入口
if __name__ =='__main__': # 它对多进程非常重要
    # 这里是主程序

# C语言的程序入口
void main(){
    /* 这里是主程序 */
}

# Java的程序入口
public static void main(String[] args){
    // 这里是主程序
}

Ponte a prueba: ¿qué imprime el siguiente programa?

# 新建一个名为【run1.py】的文件,填入下方代码
# 然后在终端输入【python3 run1.py】并运行

print(__name__, 'run1-outside')    # 它会print出【__main__ run1-outside】
if __name__ =='__main__':
    print(__name__, 'run1-inside') # 它会print出【__main__ run1-inside】

Ponte a prueba de nuevo:


# 新建另一个名为【run2.py】的文件,填入下方代码,并放在与【run1.py】的相同目录下,
# 然后在终端输入【python3 run2.py】并运行。用run2 调用run1

import run1  # 这一行代码调用了外部的代码 run1,它只会print出:
# 【run1 run1-outside】 # 它只print出这一行东西,并且run1.py的【__main__】变成了【run1】
# 【run1 run1-inside】  # 写在run1【if】缩进里的东西都没有被执行

print(__name__, 'run2-outside')    # 它会print出【__main__ run2-outside】
if __name__ =='__main__':
    print(__name__, 'run2-inside') # 它会print出【__main__ run2-inside】

Entrada de programa y programa de autocomprobación

Cuando un desarrollador escribe una biblioteca (por ejemplo, nombrándola utils.py) como


# 这个库(模块)被命名为 utils.py
class C1:
   ...
def func1():
   ...

c1 = C1()  # 这是错误的做法,应该挪到 程序入口if内部
func1()    # 这是错误的做法,应该挪到 程序入口if内部
if __name__ =='__main__':
    c = C1()
    func1()

Cuando alguien más solo quiere llamar a C1 o func1, no ejecutará ningún código dentro de la entrada del programa si está en otro archivo Python e importará la biblioteca utils con import utils.

Entrada de programa y subprocesamiento múltiple

Al implementar multihilo, la función de "entrada de programa" es indispensable. Necesito ejecutar varios fun1 al mismo tiempo, o fun1 fun2 al mismo tiempo... de la siguiente manera:


def function1(id):  # 这里是子进程
    print(f'id {id}')

def run__process():  # 这里是主进程
    from multiprocessing import Process
    process = [mp.Process(target=function1, args=(1,)),
               mp.Process(target=function1, args=(2,)), ]
    [p.start() for p in process]  # 开启了两个进程
    [p.join() for p in process]   # 等待两个进程依次结束

# run__mp()  # 主线程不建议写在 if外部。由于这里的例子很简单,你强行这么做可能不会报错
if __name__ =='__main__':
    run__mp()  # 正确做法:主线程只能写在 if内部

Cuando ejecuto el programa anterior, es [ name == ' main '], por lo que ejecutará el código dentro de [if]. Estos códigos crearán nuevos procesos secundarios múltiples que se llamarán a sí mismos. En el proceso hijo llamado, su [ nombre ] no es igual a [ principal ], por lo que solo ejecutará las tareas asignadas por el proceso principal (como fun1), y no llamará a otros procesos a través de la "entrada del programa" como el proceso principal proceso (hacer esta cosa presuntuosa). Esta es una característica muy importante, no solo Python sino también otros lenguajes de programación maduros pueden usar un enfoque similar.

RuntimeError: el contexto ya se ha establecido (multiprocesamiento) # 3492 Problema de PyTorch
Por favor agregue la descripción de la imagen
Por favor agregue la descripción de la imagen

Aunque muchas personas hacen clic en él, este análisis es correcto. Las aversiones pueden ser causadas por otras razones

Aunque forkserver todavía no es tan eficiente en recursos como spawn, no está mal para resolver el problema

Dado que mi ejemplo anterior es demasiado simple (no hay comunicación del proceso ni condiciones de salida del proceso), si fuerza que el proceso principal se escriba fuera del if, es posible que no vea un error. Hay muchos factores involucrados, tiene que ver con el sistema que está utilizando, cómo se crea el subproceso (spwan, fork, forkserver, force=True/False). Solo hablo sobre la "entrada del programa" aquí. Para obtener más información, vaya a
"Uso obligatorio de if name ==" main "en Windows mientras se usa el multiprocesamiento - Stack Overflow"
Las respuestas de Tim Peters y David Heffernan son buenas.

Aunque el multiproceso de Python ha hecho un buen trabajo, espero que con la actualización de futuras versiones, la dependencia entre multiproceso y "entrada de programa" se resuelva mejor.

Error UserWarning: semaphore_tracker al usar el multiprocesamiento PyTorch CUDA

(Escrito el 2021-03-03)

El error es el siguiente:


multiprocessing/semaphore_tracker.py:144: 
UserWarning: semaphore_tracker: There appear to be 1 leaked semaphores to clean up at shutdown
  len(cache))

Issue with multiprocessing semaphore tracking

Descripción del mismo problema:

semaphore_tracker: Parece que hay 1 semáforo filtrado para limpiar al apagar len (caché)) #200

solución:

Problema con el seguimiento de semáforos de multiprocesamiento: la solución de sbelharbi

Es decir, antes de ejecutar el archivo .py, use la siguiente declaración para modificar los parámetros del entorno, ignorando la pausa del programa causada por esta Advertencia

export PYTHONWARNINGS='ignore:semaphore_tracker:UserWarning'

Equivale a usar dentro de un archivo .py:

os.environ['PYTHONWARNINGS'] = 'ignore:semaphore_tracker:UserWarning'

Supongo que te gusta

Origin blog.csdn.net/m0_67575344/article/details/124407837
Recomendado
Clasificación