如果使用Popen启动两个python脚本,为什么我的两个python脚本之间的套接字连接断开? [英] Why does my socket connection between two python scripts break if one of them is launched with Popen?

查看:58
本文介绍了如果使用Popen启动两个python脚本,为什么我的两个python脚本之间的套接字连接断开?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有两个非常简单的python脚本,它们通过套接字进行通信.现在它们都在同一台Windows PC上运行.

这是controller.py:

import socket
import time
import sys
from subprocess import Popen, CREATE_NEW_CONSOLE

HOST = '192.168.1.107'          # The remote host
PORT = 50557                        # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.connect((HOST, PORT))
except:
    Popen([sys.executable, 'driver.py'], creationflags=CREATE_NEW_CONSOLE)
    time.sleep(0.2);
    s.connect((HOST, PORT))

s.send(sys.argv[1])
data = s.recv(1024)

s.close()
print 'Received', repr(data)

这是driver.py:

import socket

HOST = ''                                # Symbolic name meaning the local host
PORT = 50557                    # Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

while 1:
    print 'Waiting for controller connection.'
    conn, addr = s.accept()
    print 'Connected to ', addr
    while 1:
        data = conn.recv(1024)
        print 'Recieved ', data
        if not data: break
        if data == 'Q': quit()
        print 'A.'      
        conn.send(data[::-1])
        print 'B.'
    print 'C.'

conn.close()        

如果我打开两个cmd窗口并python <filename>.py <arg>它们都正常工作.我可以让driver.py运行,并一次又一次地运行controller.py.直到我通过发送"Q"杀死驱动程序.

try/except语句打开一个新窗口,如果无法建立连接,则运行driver.py.从理论上讲,这只是确保接收器在发送任何内容之前正在运行.此ALMOST可以工作,但是由于某些原因,由于我无法解释的原因,driver.py挂在第二个while循环内.以下是连续controller.py调用的输出:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

>python controller.py FirstMsg
Received 'gsMtsriF'

>python controller.py SecondMsg
Received 'gsMdnoceS'

>python controller.py Q
Received ''

>python controller.py ThirdMsg
Received 'gsMdrihT'

>python controller.py FourthMsg

(FourthMsg controller.py永远挂起之后)

这是driver.py

的输出

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

>python driver.py
Waiting for controller connection.
Connected to  ('192.168.1.107', 49915)
Recieved  FirstMsg
A.
B.
Recieved
C.
Waiting for controller connection.
Connected to  ('192.168.1.107', 49916)
Recieved  SecondMsg
A.
B.
Recieved
C.
Waiting for controller connection.
Connected to  ('192.168.1.107', 49917)
Recieved  Q

(随后返回到常规命令提示符.)用Popen创建的新窗口包含以下内容: 等待控制器连接. 已连接到('192.168.1.107',49918) 收到ThirdMsg 一种. B.

因此,在奇怪的新窗口(我刚刚注意到它看起来或不像常规的cmd窗口)中,程序似乎挂在data = conn.recv(1024)上.

为什么driver.py在新窗口中的行为有所不同,我该如何解决?

解决方案

您要求使用套接字和Popen,我的回答将忽略此问题,并尝试为用例提出解决方案,如您所见-通过网络进行远程通信./p>

使用套接字很容易遇到永无止境的问题.如果您在两个端点的控制下,zeromq通信将使您的编程恢复乐趣.

您可以直接使用zeromq(如果查看pyzmq的示例,您会发现它们确实很简短,并且在许多困难的情况下都能很好地工作),但是今天我将展示zerorpc库的用法,这使得远程呼叫更加简单.

安装zerorpc

$ pip install zerorpc

写下您的worker.py

def reverse(text):
    """ return reversed argument """
    return text[::-1]

def makebig(text):
    """ turn text to uppercase letters """
    return text.upper()

从命令行调用辅助方法

启动服务器以提供worker.py功能

$ zerorpc --server --bind tcp://*:5555 worker
binding to "tcp://*:5555"
serving "worker"

使用服务(从命令行)

简单的调用,报告要调用的可用功能

$ zerorpc tcp://localhost:5555
connecting to "tcp://localhost:5555"
makebig turn text to uppercase letters 
reverse return reversed argument 

然后调用这些函数:

$ zerorpc tcp://localhost:5555 reverse "alfabeta"
connecting to "tcp://localhost:5555"
'atebafla'

$ zerorpc tcp://localhost:5555 makebig "alfabeta"
connecting to "tcp://localhost:5555"
'ALFABETA'

注意:到目前为止,我们已经编写了7行代码,并且已经能够远程调用它.

使用Python代码

命令行实用程序zerorpc只是方便的实用程序,但是您可以自由地使用纯Python进行集成,而无需使用它.

使用python代码client.py

import zerorpc

client = zerorpc.Client()
url = "tcp://localhost:5555"
client.connect(url)

print client.reverse("alfabeta")
print client.makebig("alfabeta")

并运行它

$ python client.py
atebafla
ALFABETA

从python代码server.py

运行远程服务器

import zerorpc
import worker

url = "tcp://*:5555"

srv = zerorpc.Server(worker)
srv.bind(url)
srv.run()

如果命令仍在运行,请停止通过命令zerorpc启动的旧服务器.

然后启动服务器的python版本:

$ python server.py

(它不会打印任何内容,只是等待投放).

最后,从您的Python代码中使用它

$ python client.py 
atebafla
ALFABETA

结论

  • 使用zeromq或zerorpc大大简化了情况
  • 以不同的顺序播放client.py和server.py.
  • 尝试运行多个客户端
  • 尝试通过网络使用另一台计算机上的服务
  • zerorpc提供了更多模式(流媒体,发布/订阅),请参见zerorpc测试套件
  • zerorpc解决了集成任务,让您专注于对实函数进行编码

So I have two very simple python scripts that communicate over a socket. Right now they are both running on the same windows PC.

Here's controller.py:

import socket
import time
import sys
from subprocess import Popen, CREATE_NEW_CONSOLE

HOST = '192.168.1.107'          # The remote host
PORT = 50557                        # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.connect((HOST, PORT))
except:
    Popen([sys.executable, 'driver.py'], creationflags=CREATE_NEW_CONSOLE)
    time.sleep(0.2);
    s.connect((HOST, PORT))

s.send(sys.argv[1])
data = s.recv(1024)

s.close()
print 'Received', repr(data)

And here's driver.py:

import socket

HOST = ''                                # Symbolic name meaning the local host
PORT = 50557                    # Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

while 1:
    print 'Waiting for controller connection.'
    conn, addr = s.accept()
    print 'Connected to ', addr
    while 1:
        data = conn.recv(1024)
        print 'Recieved ', data
        if not data: break
        if data == 'Q': quit()
        print 'A.'      
        conn.send(data[::-1])
        print 'B.'
    print 'C.'

conn.close()        

If I open two cmd windows and python <filename>.py <arg> them both everything works fine. I can leave driver.py running and run controller.py over and over again. Until I kill the driver by sending a "Q".

The try/except statement opens up a new window and runs driver.py if the connection can't be made. Theoretically this just makes sure that the receiver is running before it sends anything. This ALMOST works but for some reason driver.py hangs inside the second while loop for reasons I cannot explain. Here's the output from sequential controller.py calls:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

>python controller.py FirstMsg
Received 'gsMtsriF'

>python controller.py SecondMsg
Received 'gsMdnoceS'

>python controller.py Q
Received ''

>python controller.py ThirdMsg
Received 'gsMdrihT'

>python controller.py FourthMsg

(After FourthMsg controller.py hangs forever)

Here's the output from driver.py

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

>python driver.py
Waiting for controller connection.
Connected to  ('192.168.1.107', 49915)
Recieved  FirstMsg
A.
B.
Recieved
C.
Waiting for controller connection.
Connected to  ('192.168.1.107', 49916)
Recieved  SecondMsg
A.
B.
Recieved
C.
Waiting for controller connection.
Connected to  ('192.168.1.107', 49917)
Recieved  Q

(Whereupon it returns to the regular command prompt.) The new window created with Popen contains this: Waiting for controller connection. Connected to ('192.168.1.107', 49918) Recieved ThirdMsg A. B.

So in the weird new window (which I just noticed does not look or act like a regular cmd window) the program seems to hang on data = conn.recv(1024).

Why does driver.py act differently in the new window, and how can I fix it?

解决方案

You asked for sockets and Popen, my answer will ignore this and will try to propose solution for the use case, you have shown - remote communication over network.

With sockets it is very easy to run into never ending problems. If you have both endpoints under your control, zeromq communication will turn your programming back to having fun.

You may either use zeromq directly (if you check examples for pyzmq, you will find they are really short and easy while serving very well in many difficult scenarios), but today I will show use of zerorpc library, which makes remote calls even simpler.

Install zerorpc

$ pip install zerorpc

Write your worker.py

def reverse(text):
    """ return reversed argument """
    return text[::-1]

def makebig(text):
    """ turn text to uppercase letters """
    return text.upper()

Call worker methods from command line

Start server serving worker.py functions

$ zerorpc --server --bind tcp://*:5555 worker
binding to "tcp://*:5555"
serving "worker"

Consume the services (from command line)

Simple call, reporting available functions to call

$ zerorpc tcp://localhost:5555
connecting to "tcp://localhost:5555"
makebig turn text to uppercase letters 
reverse return reversed argument 

Then call these functions:

$ zerorpc tcp://localhost:5555 reverse "alfabeta"
connecting to "tcp://localhost:5555"
'atebafla'

$ zerorpc tcp://localhost:5555 makebig "alfabeta"
connecting to "tcp://localhost:5555"
'ALFABETA'

Note: so far we have wrote 7 lines of code and are already able calling it remotely.

Using from Python code

Command line utility zerorpc is just handy utility, but you are free to integrate without it, using pure Python.

Consuming from python code client.py

import zerorpc

client = zerorpc.Client()
url = "tcp://localhost:5555"
client.connect(url)

print client.reverse("alfabeta")
print client.makebig("alfabeta")

and run it

$ python client.py
atebafla
ALFABETA

Run remote server from python code server.py

import zerorpc
import worker

url = "tcp://*:5555"

srv = zerorpc.Server(worker)
srv.bind(url)
srv.run()

Stop older server started by command zerorpc, if it still runs.

Then start out python version of the server:

$ python server.py

(it does not print anything, just waits to serve).

Finally, consume it from your Python code

$ python client.py 
atebafla
ALFABETA

Conclusions

  • Using zeromq or zerorpc simplifies the situation a lot
  • Play with starting client.py and server.py in various orders
  • try to run multiple clients
  • try to consume services from another computer (over network)
  • zerorpc provides more patterns (streamer, publish/subscribe), see zerorpc test suite
  • zerorpc solves the integration task and let you focus on coding real functions

这篇关于如果使用Popen启动两个python脚本,为什么我的两个python脚本之间的套接字连接断开?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆