Spawn multiprocessing.Process在不同的python可执行文件下使用自己的路径

时间:2016-09-07 14:31:18

标签: python python-multiprocessing conda

我有两个版本的Python(实际上是两个conda环境)

/path/to/bin-1/python
/path/to/bin-2/python

从python的一个版本开始,我想使用类似multiprocessing.Process对象的东西启动另一个版本中运行的函数。事实证明,使用set_executable方法可行:

ctx = multiprocess.get_context('spawn')
ctx.set_executable('/path/to/bin-2/python')

事实上,我们可以看到这实际上是使用该可执行文件启动的:

def f(q):
    import sys
    q.put(sys.executable)

if __name__ == '__main__':
    import multiprocessing
    ctx = multiprocessing.get_context('spawn')
    ctx.set_executable('/path/to/bin-2/python')
    q = ctx.Queue()
    proc = ctx.Process(target=f, args=(q,))
    proc.start()
    print(q.get())

$ python foo.py
/path/to/bin-2/python

但路径错误

然而,当我使用sys.path而不是sys.executable执行相同的操作时,我发现托管python进程的sys.path是打印出来的,而不是我发现的sys.path直接运行/path/to/bin-2/python -c "import sys; print(sys.path)"

如果我使用fork,我习惯了这种事情。我本来期望'spawn'的行为与我从shell中输入python解释器一样。

问题

是否可以使用多处理库来运行函数,并使用其他Python可执行文件中的队列以及从shell启动它时的环境?

更广泛地说,如何填充sys.path以及以这种方式使用多处理和直接启动解释器之间有什么不同?

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。我的系统级Python可执行文件位于 col_01_01 col_02_01 col_01_02 col_02_02 output 0 NaN NaN 0 1 1 1 NaN NaN 0 0 0 2 1.0 1.0 0 0 1 3 2.0 2.0 0 1 1 4 NaN NaN 1 1 1 ,并且我使用/path/to/bin-1/python创建了一个虚拟环境,其中包含位于virtualenv的另一个Python可执行文件。为了为/path/to/bin-2/python所需的生成过程设置正确的路径/环境,我最终将代码从/path/to/bin-2/python文件夹中的activate_this.py复制到virtualenv

f(q)

标准输出:

def f(q):
    import sys, os

    def active_virtualenv(exec_path):
        """
        copy virtualenv's activate_this.py
        exec_path: the python.exe path from sys.executable
        """
        # set env. var. PATH
        old_os_path = os.environ.get('PATH', '')
        os.environ['PATH'] = os.path.dirname(os.path.abspath(exec_path)) + os.pathsep + old_os_path
        base = os.path.dirname(os.path.dirname(os.path.abspath(exec_path)))
        # site-pachages path
        if sys.platform == 'win32':
            site_packages = os.path.join(base, 'Lib', 'site-packages')
        else:
            site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
        # modify sys.path
        prev_sys_path = list(sys.path)
        import site
        site.addsitedir(site_packages)
        sys.real_prefix = sys.prefix
        sys.prefix = base
        # Move the added items to the front of the path:
        new_sys_path = []
        for item in list(sys.path):
            if item not in prev_sys_path:
                new_sys_path.append(item)
                sys.path.remove(item)
        sys.path[:0] = new_sys_path
        return None

    active_virtualenv(sys.executable)
    q.put(sys.executable)
    # check some unique package in this env.
    import special_package
    print "package version: {}".format(special_package.__version__)


if __name__ == '__main__':
    import multiprocessing
    multiprocessing.set_executable('/path/to/bin-2/python')
    q = multiprocessing.Queue()
    proc = multiprocessing.Process(target=f, args=(q,))
    proc.start()
    proc.join()
    print(q.get())

我不确定的一件事是{{1}之前的$ python foo.py /path/to/bin-2/python package version: unique_version_only_in_virtualenv sysos,这意味着它们来自系统范围的Python env。但是我在import中需要的其他软件包来自虚拟环境。切换环境后,也许值得重新active_virtualenv()