如何在不同conda环境的两个不同python进程之间交换数据?

问题描述 投票:0回答:2

A 和 B 两个 python 脚本存在兼容性问题,需要单独的 conda 环境。这是场景。当脚本 A 运行时,它向进程 B 发送数据(脚本 B 在不同的终端中运行),进程 B 将输出返回给进程 A(进程 A 无法进入休眠状态)。我一直在使用 pickle 文件在这两个进程之间交换数据,但这种方法似乎很慢,我想加快速度,这对我的工作是必要的。

python ipc
2个回答
1
投票
  1. 使用 subprocess 模块使一个程序成为另一个程序的子程序,并通过 stdin 和 stdout 进行通信。 (最快)(注意你必须在命令中激活其他 anaconda 环境才能启动孩子)
  2. 让一个应用程序成为服务器并连接到本地主机上的套接字,另一个应用程序将成为使用 socket 模块的客户端。 (最具组织性和可扩展性的解决方案)
  3. 使内存的一部分成为共享内存,两个应用程序都可以使用 multiprocessing.shared_memory(需要适当的同步,但可以比一次传输 GB 数据的第一个选项更快),(包装它在
    io.TextIOWrapper
    中将使通信更容易,就像使用套接字一样简单)

0
投票

你可以使用parent.py,调用child.sh来设置conda环境,然后调用child.py 例如使用 zmq 进行通信(下面的辅助模块)

**父母.py

import numpy as np
from subprocess import call
from communicator import EZZMQ

# set up the communicator
zmq_port, send, recv = EZZMQ(None)

# call child with port info
call(f'./child.sh {zmq_port}', shell=True)

def child_process(data):
    send(data) # send
    # something done by child
    return recv() #receive

# create data
data = np.random.random((3,3))
transformed_data = child_process(data)
print('data', data)
print('transformed data', transformed_data)

child.sh:

# !/bin/bash
# set up environment variables and conda
source $HOME/git/lcls2/setup_env.sh 

# echo "using port: $1"
python child.py  $1 &

child.py

import numpy as np
import sys
from communicator import EZZMQ

# get the port info
zmq_port = sys.argv[1] 

#bind the port
zmq_port, send, recv = EZZMQ(zmq_port)

# get the data
data = recv()

# transform
data=data+1

# send back
data = send(data)

和一个助手“communicator.py”模块

import zmq
import zlib, pickle

port_selected = None

def EZZMQ(port): # None will start the parent 
  context = zmq.Context()
  zmq_socket = context.socket(zmq.PAIR)

  if type(port)==type(None): # parent to select the port
     port_selected = zmq_socket.bind_to_random_port('tcp://*', min_port=50000, max_port=65004, max_tries=1000)
  else: # child is given the port 
     zmq_socket.connect("tcp://localhost:%s" % port)
     port_selected = int(port) 

  def send(obj, flags=0, protocol=-1):
        """pickle an object, and zip the pickle before sending it"""
        p = pickle.dumps(obj, protocol)
        z = zlib.compress(p)
        return zmq_socket.send(z, flags=flags)
  def recv(flags=0, protocol=-1):
        """inverse of send_zipped_pickle"""
        z = zmq_socket.recv(flags)
        p = zlib.decompress(z)
        return pickle.loads(p)
  return port_selected, send, recv
© www.soinside.com 2019 - 2024. All rights reserved.