簡體   English   中英

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

[英]Spawn multiprocessing.Process under different python executable with own path

我有兩個版本的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被打印出來,而不是我從運行/path/to/bin-2/python -c "import sys; print(sys.path)"找到的sys.path /path/to/bin-2/python -c "import sys; print(sys.path)"直接。

如果我使用fork,我習慣了這種事情。 我本來希望'spawn'的行為與我從shell中輸入python解釋器一樣。

是否可以使用多處理庫來運行函數,並使用其他Python可執行文件中的隊列以及從shell啟動它時所具有的環境?

更廣泛地說,如何填充sys.path以及以這種方式使用多處理和直接啟動解釋器之間有什么不同?

我遇到了同樣的問題。 我的系統范圍的Python可執行文件位於/path/to/bin-1/python ,我使用virtualenv/path/to/bin-2/python創建了一個包含另一個Python可執行文件的虛擬環境。 要為/path/to/bin-2/python所需的生成進程設置正確的路徑/環境,我最終將virtualenv文件夾中activate_this.py的代碼復制到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())

stdouts:

$ python foo.py
/path/to/bin-2/python
package version: unique_version_only_in_virtualenv

我不太確定的一件事是sysos是在active_virtualenv()之前import ,這意味着它們來自系統范圍的Python環境。 但我在f(q)中需要的其他包來自虛擬環境。 也許在切換env后重新import它們是值得的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM