Je veux arrêter un pymodbus async ModbusTcpServer puis démarrer un nouveau serveur. Par conséquent, j'ai essayé avec l'extrait de code simplifié suivant, mais j'ai eu une erreur:
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
Out:
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()
[UPDATE]
J'ai également essayé avec un autre thread d'arrêter le ModbusTcpServer avec l'argument defer_reactor_run = False (par défaut) dans ModbusTcpServer , mais malgré cela, le comportement reste le même:
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.
Out:
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()
3 Réponses :
Dans le premier exemple, le serveur TCP n'est pas exécuté depuis que vous avez défini le paramètre defer_reactor_run sur True, mais vous ne l'avez pas explicitement exécuté. Ainsi, lorsque vous essayez de l'arrêter, il échoue car il n'a pas été démarré.
Dans le deuxième exemple, vous l'exécutez, mais vous l'appelez une prochaine fois de manière récursive avec l'appel principal (name)! donc, il échoue avec une erreur puisqu'il est déjà démarré! le code suivant devrait fonctionner:
from twisted.internet import reactor
StartTcpServer(context, identity=identity, address=("localhost", 5020),
defer_reactor_run=True)
reactor.run()
Si vous voulez différer l'exécution, vous devez appeler:
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=False
)
sleep(3) # for the fun ?
# and do your stuff
StopServer()
main()
Dans le deuxième exemple, j'arrête le réacteur par un autre thread après 5sec avec le StopServer () intégré dans pymodbus
peut-être, mais en attendant, vous essayez de redémarrer le serveur déjà démarré, avant que le minuteur ne se réveille.
Avez-vous essayé cet extrait de code? Ce code est coincé dans StartTcpServe () car defer_reactor_run est faux. Cependant, je souhaite arrêter et redémarrer le serveur
Il n'est pas bloqué, il exécute un serveur .... si vous voulez l'arrêter, tuez la tâche. J'ai mis à jour comment l'exécuter en mode différé
Ma question est évidente, ce n'est pas ma réponse, et merci pour la réponse.
Je n'ai aucun problème pour exécuter le serveur, je veux exécuter un serveur puis l'arrêter puis démarrer le serveur avec un nouveau contenu pour une raison quelconque (mon code de question est simplifié du code pour simuler ce que je veux). Si je n'ai pas trouvé de réponse pour redémarrer une boucle réacteur je le fais par un autre code
J'ai trouvé une solution alternative pour arrêter et démarrer un Async ModbusTcpServer par un autre code Python car apparemment, nous ne pouvons pas redémarrer une boucle d'événement réacteur .
Voici le runner.py code:
$ python3 runner.py 2019-01-24 12:45:05,126 MainThread INFO async :254 Starting Modbus TCP Server on localhost:5020 2019-01-24 12:45:10,129 Thread-1 DEBUG async :222 Running in spawned thread 2019-01-24 12:45:10,129 Thread-1 DEBUG async :332 Stopping Server from another thread b'Start an async server.\nProcess will be down.\nServer was stopped.\n' 2019-01-24 12:45:13,389 MainThread INFO async :254 Starting Modbus TCP Server on localhost:5020 2019-01-24 12:45:18,392 Thread-1 DEBUG async :222 Running in spawned thread 2019-01-24 12:45:18,392 Thread-1 DEBUG async :332 Stopping Server from another thread b'Start an async server.\nProcess will be down.\nServer was stopped.\n' 2019-01-24 12:45:21,653 MainThread INFO async :254 Starting Modbus TCP Server on localhost:5020 2019-01-24 12:45:26,656 Thread-1 DEBUG async :222 Running in spawned thread 2019-01-24 12:45:26,657 Thread-1 DEBUG async :332 Stopping Server from another thread b'Start an async server.\nProcess will be down.\nServer was stopped.\n' . . .
Voici l'extrait de code 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()
Sortie:
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()
Vous pouvez utiliser l'exemple inclus dans les dossiers de la bibliothèque: asynchronous-server.py
dans python3.7 async a été inclus comme mot-clé, mais dans pymodbus 2.3.0 pymodbus.server.async a été changé en pymodbus.server. asynchrone
Je vous partage un exemple qui fonctionne bien pour moi:
Si vous avez d'autres questions, écrivez-moi à l'adresse e-mail: Danielsalazr@hotmail.com
< pre> XXXSalutations de Colombie
Bonjour Daniel, Depuis que cette bibliothèque pymodbus a été mise à jour, pymodbus.server.async a été transformé en pymodbus.server.asynchronous dans la nouvelle version et je suis conscient (ma question a été posée il y a un an avec la version antérieure de pymodbus). Cependant, ce n'est pas mon problème. Comme je l'ai mentionné dans la question, le problème est StopServer et non StartTcpServer