怎么停止一台pymodbus Async Modbus TcpServer?

本教程将介绍如何停止一台pymodbus Async Modbus TcpServer?的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

怎么停止一台pymodbus Async Modbus TcpServer? 教程 第1张

问题描述

我要停止pymodbus异步ModbusTcpServer,然后启动新服务器。因此,我尝试使用以下简化的代码片段,但收到错误:

from pymodbus.server.async import StartTcpServer, StopServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from time import sleep

import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

def main(name='Pymodbus'):
 store = ModbusSlaveContext(hr=ModbusSequentialDataBlock(0, [17]*100))
 context = ModbusServerContext(slaves=store, single=True)

 identity = ModbusDeviceIdentification()
 identity.VendorName = name
 identity.ProductCode = 'PM'
 identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
 identity.ProductName = 'Pymodbus Server'
 identity.ModelName = 'Pymodbus Server'
 identity.MajorMinorRevision = '1.0'

 StartTcpServer(
  context,
  identity=identity,
  address=("localhost", 5020),
  defer_reactor_run=True
 )
 sleep(3)
 name += 'stuff'

 StopServer()
 sleep(3)
 main(name)  # Recursive

main()

输出:

INFO:pymodbus.server.async:Starting Modbus TCP Server on localhost:5020
DEBUG:pymodbus.server.async:Running in Main thread
Traceback (most recent call last):
  File "stack.py", line 42, in <module>
 main()
  File "stack.py", line 38, in main
 StopServer()
  File "/usr/local/lib/python3.6/dist-packages/pymodbus/server/async.py", line 328, in StopServer
 reactor.stop()
  File "/usr/local/lib/python3.6/dist-packages/twisted/internet/base.py", line 630, in stop
 "Can't stop reactor that isn't running.")
twisted.internet.error.ReactorNotRunning: Can't stop reactor that isn't running.

[更新]

此外,我还尝试使用另一个线程在ModbusTcpServer中使用defer_reactor_run=False参数(作为默认)停止ModbusTcpServer,但尽管如此,行为仍然是相同的:

import threading
import logging
from pymodbus.server.async import StartTcpServer, StopServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

def stop():
 StopServer()

def main(name='Pymodbus'):
 store = ModbusSlaveContext(hr=ModbusSequentialDataBlock(0, [17]*100))
 context = ModbusServerContext(slaves=store, single=True)

 identity = ModbusDeviceIdentification()
 identity.VendorName = name
 identity.ProductCode = 'PM'
 identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
 identity.ProductName = 'Pymodbus Server'
 identity.ModelName = 'Pymodbus Server'
 identity.MajorMinorRevision = '1.0'

 t = threading.Timer(5, stop)
 t.daemon = True
 t.start()

 StartTcpServer(
  context,
  identity=identity,
  address=("localhost", 5020),
  defer_reactor_run=False
 )
 name += 'stuff'

 main(name)  # Recursive

main()

输出:

INFO:pymodbus.server.async:Starting Modbus TCP Server on localhost:5020
DEBUG:pymodbus.server.async:Running in Main thread
DEBUG:pymodbus.server.async:Running in spawned thread
DEBUG:pymodbus.server.async:Stopping Server from another thread
INFO:pymodbus.server.async:Starting Modbus TCP Server on localhost:5020
DEBUG:pymodbus.server.async:Running in Main thread
Traceback (most recent call last):
  File "stack.py", line 41, in <module>
 main()
  File "stack.py", line 39, in main
 main()  # Recursive
  File "stack.py", line 35, in main
 defer_reactor_run=False
  File "/usr/local/lib/python3.6/dist-packages/pymodbus/server/async.py", line 257, in StartTcpServer
 reactor.run(installSignalHandlers=_is_main_thread())
  File "/usr/local/lib/python3.6/dist-packages/twisted/internet/base.py", line 1260, in run
 self.startRunning(installSignalHandlers=installSignalHandlers)
  File "/usr/local/lib/python3.6/dist-packages/twisted/internet/base.py", line 1240, in startRunning
 ReactorBase.startRunning(self)
  File "/usr/local/lib/python3.6/dist-packages/twisted/internet/base.py", line 748, in startRunning
 raise error.ReactorNotRestartable()
twisted.internet.error.ReactorNotRestartable

推荐答案

我找到了另一个解决方案,可以通过另一个Python代码停止和启动异步Modbus TcpServer,因为很明显,我们无法重新启动reactor事件循环。


这是runner.py代码:

import subprocess

python_version = '3'
path_to_run = './'
py_name = 'async_server.py'

def run():
 args = [f"python{python_version}", f"{path_to_run}{py_name}"]
 sub_process = subprocess.Popen(args, stdout=subprocess.PIPE)
 output, error_ = sub_process.communicate()

 if not error_:
  print(output)
 else:
  print(error_)

 run()  # Recursively.

if __name__ == '__main__':
 run()

这是async_server.py代码片段:

from pymodbus.server.async import StartTcpServer, StopServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

import threading
import sys
import logging

FORMAT = ('%(asctime)-15s %(threadName)-15s'
 ' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

def stop():
 print('Process will be down.')
 StopServer()  # Stop server.
 sys.exit(0)  # Kill the server code.

def run_async_server():
 store = ModbusSlaveContext(hr=ModbusSequentialDataBlock(0, [17] * 100))
 slaves = {
  0x01: store,
  0x02: store,
  0x03: store,
 }
 context = ModbusServerContext(slaves=slaves, single=False)

 identity = ModbusDeviceIdentification()
 identity.VendorName = 'Pymodbus'
 identity.ProductCode = 'PM'
 identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
 identity.ProductName = 'Pymodbus Server'
 identity.ModelName = 'Pymodbus Server'
 identity.MajorMinorRevision = '1.5'

 from twisted.internet import reactor
 StartTcpServer(context, identity=identity, address=("localhost", 5020),
 defer_reactor_run=True)
 print('Start an async server.')
 t = threading.Timer(5, stop)
 t.daemon = True
 t.start()
 reactor.run()
 print('Server was stopped.')

if __name__ == "__main__":
 run_async_server()

输出:

$ python3 runner.py 

2019-01-24 12:45:05,126 MainThreadINFO  async :254Starting Modbus TCP Server on localhost:5020
2019-01-24 12:45:10,129 Thread-1  DEBUG async :222Running in spawned thread
2019-01-24 12:45:10,129 Thread-1  DEBUG async :332Stopping Server from another thread
b'Start an async server.
Process will be down.
Server was stopped.
'
2019-01-24 12:45:13,389 MainThreadINFO  async :254Starting Modbus TCP Server on localhost:5020
2019-01-24 12:45:18,392 Thread-1  DEBUG async :222Running in spawned thread
2019-01-24 12:45:18,392 Thread-1  DEBUG async :332Stopping Server from another thread
b'Start an async server.
Process will be down.
Server was stopped.
'
2019-01-24 12:45:21,653 MainThreadINFO  async :254Starting Modbus TCP Server on localhost:5020
2019-01-24 12:45:26,656 Thread-1  DEBUG async :222Running in spawned thread
2019-01-24 12:45:26,657 Thread-1  DEBUG async :332Stopping Server from another thread
b'Start an async server.
Process will be down.
Server was stopped.
'
.
.
.

好了关于怎么停止一台pymodbus Async Modbus TcpServer?的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。