Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 确定是否从没有主保护的函数调用_Python_Windows_Multithreading - Fatal编程技术网

Python 确定是否从没有主保护的函数调用

Python 确定是否从没有主保护的函数调用,python,windows,multithreading,Python,Windows,Multithreading,如果模块是从没有主保护的脚本导入的(如果_uname__=='_umain_;':),在模块中的某些函数中执行任何类型的并行操作都将导致Windows上的无限循环。每个新进程加载所有源,现在\uuuu name\uuuu不等于'\uuu main\uuuu',然后并行执行。如果没有主保护,我们将在每个新进程中对同一函数进行另一次调用,生成更多进程,直到崩溃。这只是Windows上的一个问题,但脚本也在osx和linux上执行 我可以通过写入磁盘上的一个特殊文件来检查这一点,然后从中读取,看看我们

如果模块是从没有主保护的脚本导入的(
如果_uname__=='_umain_;':
),在模块中的某些函数中执行任何类型的并行操作都将导致Windows上的无限循环。每个新进程加载所有源,现在
\uuuu name\uuuu
不等于
'\uuu main\uuuu'
,然后并行执行。如果没有主保护,我们将在每个新进程中对同一函数进行另一次调用,生成更多进程,直到崩溃。这只是Windows上的一个问题,但脚本也在osx和linux上执行

我可以通过写入磁盘上的一个特殊文件来检查这一点,然后从中读取,看看我们是否已经开始了,但这限制了我们一次只能运行一个python脚本。修改所有调用代码以添加主防护的简单解决方案是不可行的,因为它们分布在许多存储库中,我无法访问这些存储库。因此,当使用主保护时,我想并行化,但当不使用主保护时,我想回退到单线程执行

我如何判断是否由于缺少主保护而在导入循环中被调用,以便回退到单线程执行

这里有一些演示代码:

具有并行代码的库:

from multiprocessing import Pool


def _noop(x):
    return x


def foo():
    p = Pool(2)
    print(p.map(_noop, [1, 2, 3]))
好的进口商(带护罩):

不良进口商(无防护装置):

如果错误导入程序因此运行时错误而失败,请反复执行以下操作:

    p = Pool(2)
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\context.py", line 118, in Pool
    context=self.get_context())
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\pool.py", line 168, in __init__
    self._repopulate_pool()
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\pool.py", line 233, in _repopulate_pool
    w.start()
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\process.py", line 105, in start
    self._popen = self._Popen(self)
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\context.py", line 313, in _Popen
    return Popen(process_obj)
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\popen_spawn_win32.py", line 34, in __init__
    prep_data = spawn.get_preparation_data(process_obj._name)
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 144, in get_preparation_data
    _check_not_importing_main()
  File "C:\Users\filip.haglund\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 137, in _check_not_importing_main
    is not going to be frozen to produce an executable.''')
RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.

由于您使用的是
多处理
,因此还可以使用它来检测您是主进程还是子进程。但是,这些特性没有文档记录,因此只是实现细节,在不同的python版本之间可能会在没有警告的情况下更改

每个进程都有一个
名称
\u标识
\u父进程
。您可以检查其中任何一个,看看您是否处于主流程中。在主进程中,
名称
将是
'MainProcess'
\u标识
将是
()
\u父进程
将是

我的解决方案允许您继续使用
多处理
,但只是修改子进程,使它们不能永远创建子进程。它使用修饰符将子进程中的
foo
更改为no-op,但在主进程中返回
foo
unchanged。这意味着当派生的子进程尝试执行
foo
时,将不会发生任何事情(就好像它是在
\uuuuuuu主\uuuuu
保护中执行的一样)

from multiprocessing import Pool
from multiprocessing.process import current_process

def run_in_main_only(func):
    if current_process().name == "MainProcess":
        return func
    else:
        def noop(*args, **kwargs):
            pass
        return noop

def _noop(_ignored):
    p = current_process()
    return p.name, p._identity, p._parent_pid

@run_in_main_only
def foo():
    with Pool(2) as p:
        for result in p.map(_noop, [1, 2, 3]):
            print(result) # prints something like ('SpawnPoolWorker-2', (2,), 10720)

if __name__ == "__main__":
    print(_noop(1)) # prints ('MainProcess', (), None)

由于您使用的是
多处理
,因此您还可以使用它来检测您是主进程还是子进程。但是,这些功能没有文档记录,因此只是实现细节,在python版本之间可能会在没有警告的情况下更改

每个进程都有一个
名称
\u标识
\u父进程
。您可以检查它们中的任何一个,看看您是否在主进程中。在主进程中
名称
将是
'MainProcess'
\u标识
将是
(),
\u父进程将是

我的解决方案允许您继续使用
多处理
,但只是修改子进程,使它们不能永远创建子进程。它使用修饰符将子进程中的
foo
更改为no-op,但在主进程中返回
foo
unchanged。这意味着当派生的子进程尝试执行
foo
时,将不会发生任何事情(就好像它是在
\uuuuuuu主\uuuuu
保护中执行的一样)

from multiprocessing import Pool
from multiprocessing.process import current_process

def run_in_main_only(func):
    if current_process().name == "MainProcess":
        return func
    else:
        def noop(*args, **kwargs):
            pass
        return noop

def _noop(_ignored):
    p = current_process()
    return p.name, p._identity, p._parent_pid

@run_in_main_only
def foo():
    with Pool(2) as p:
        for result in p.map(_noop, [1, 2, 3]):
            print(result) # prints something like ('SpawnPoolWorker-2', (2,), 10720)

if __name__ == "__main__":
    print(_noop(1)) # prints ('MainProcess', (), None)

您能创建一个流程生成程序的列表吗?至少告诉我们您用于生成流程的策略/模块(,或)?这将是
多处理
:)您能创建一个流程生成程序的列表吗?至少告诉我们,您使用哪种策略/模块来生成进程(,或)?这将是
多处理
:)
from multiprocessing import Pool
from multiprocessing.process import current_process

def run_in_main_only(func):
    if current_process().name == "MainProcess":
        return func
    else:
        def noop(*args, **kwargs):
            pass
        return noop

def _noop(_ignored):
    p = current_process()
    return p.name, p._identity, p._parent_pid

@run_in_main_only
def foo():
    with Pool(2) as p:
        for result in p.map(_noop, [1, 2, 3]):
            print(result) # prints something like ('SpawnPoolWorker-2', (2,), 10720)

if __name__ == "__main__":
    print(_noop(1)) # prints ('MainProcess', (), None)