【发布时间】:2014-07-15 22:38:33
【问题描述】:
我正在使用 python 2.5.2 或 2.7,这是一个启动各种任务的 HTTP 服务器 (BaseHTTPServer)。其中一个进程是一个长时间运行的进程。我想做的是启动这个过程,然后关闭我的 HTTP 服务器并重新启动。
问题是我的服务器关闭(关闭所有线程并且python.exe进程退出Windows显示的活动任务列表,启动的进程仍在运行,但netstat -ab显示系统进程有我的HTTP 服务器在 LISTENING 状态下侦听的端口,并与曾经是我的 HTTP 服务器的进程 ID 相关联。该端口保持打开状态,直到启动的进程完成,这使得我无法重新启动我的 HTTP 服务器。
无论我是杀死 python 进程,还是 CTRL-C 窗口,都会表现出相同的行为。我已经阅读了大量文档,每个人都建议使用 subprocess.Popen,但即使使用它似乎也会将主进程的某些部分与启动的进程相关联。
我按如下方式启动该实用程序:
try:
# NOTE: subprocess.Popen is hanging up the 8091 port until the utility finishes.
# This needs to be addressed, otherwise, I'll never be able to restart the
# client when the utility has been launched.
listParams = [ 'C:/MyPath/My.exe', '-f', os.path.join ( sXMLDir, sXmlFile ) ]
proc = subprocess.Popen ( listParams, cwd='C:/MyPath', creationflags=0x00000008 )
iSts = 200
sStatus = 'Utility was successfully launched.'
except:
iSts = CMClasses.HTTPSTS_STARTSLEDGE_SYSTEM
sStatus = 'An exception occurred launching utility: ' + str ( sys.exc_type ) + ":" + str ( sys.exc_value ) + '.'
我的 HTTP 服务器实现如下,它允许我的主程序处理 CTRL-C:
class LaunchHTTPServer ( Thread ):
def __init__ ( self, sPort, CMRequestHandler ):
Thread.__init__ ( self )
self.notifyWindow = None
self.Port = sPort
self.CMRequestHandler = CMRequestHandler
self.bExecute = True
def run ( self ):
server = stoppableHttpServer(('',self.Port), self.CMRequestHandler )
server.serve_forever()
server.socket.close()
def getExecute ( self ):
return ( self.bExecute )
def endThread ( self ):
pass
class stoppableHttpServer ( BaseHTTPServer.HTTPServer ):
def serve_forever ( self ):
self.stop = False
while not self.stop:
self.handle_request()
def main ( argv ):
...
try:
....
tLaunchHTTPServer = LaunchHTTPServer ( iCMClientPort, CMRequestHandler )
tLaunchHTTPServer.start()
...
except KeyboardInterrupt:
logging.info ( 'main: Request to stop received' )
# End the communication threads
logging.info ( 'Requesting CMRequestHandler to close.' )
conn = httplib.HTTPConnection ( "localhost:%d" % iCMClientPort )
conn.request ( "QUIT", "/" )
conn.getresponse()
conn.close()
这是启动实用程序之前 netstat -ab 的结果(我的 python 进程是 3728,我的端口是 8091):
活动连接
原始本地地址外部地址状态PID
TCP vtxshm-po-0101:8091 vtxshm-po-0101:0 监听 3728 [python.exe]
TCP vtxshm-po-0101:8091 vtxshm-po-0101:23193 TIME_WAIT 0 [框架服务.exe]
以下是 netstat -ab 在启动实用程序后以及按 Control-C 并停止 python 后的结果。 (请注意,操作系统认为此端口仍处于侦听状态,分配给 PID 3728,但该进程不再存在于任务管理器中,现在归系统所有,并且与 snmp.exe 有某种关联(我们不甚至使用))。这些连接被理解为来自另一台服务器的启动实用程序的请求。
活动连接
原始本地地址外部地址状态PID
TCP vtxshm-po-0101:8091 vtxshm-po-0101:0 监听 3728 [系统]
TCP vtxshm-po-0101:8091 CH2ChaosMonkeyServer:2133 TIME_WAIT 0 TCP vtxshm-po-0101:8091 CH2ChaosMonkeyServer:2134 TIME_WAIT 0 TCP vtxshm-po-0101:8091 vtxshm-po-0101:23223 TIME_WAIT 0 [snmp.exe]
有没有人成功地从 python 启动了一个进程并完全独立于启动进程运行?如果是这样,你能分享一下这个秘密吗?
【问题讨论】:
标签: python subprocess popen httpserver socketserver