FreeOpcUa / python-opcua

LGPL Pure Python OPC-UA Client and Server
http://freeopcua.github.io/
GNU Lesser General Public License v3.0
1.36k stars 658 forks source link

Create server node from different process #883

Open Lukas1811 opened 5 years ago

Lukas1811 commented 5 years ago

My program is running in multiple different processes, one of them is running the OPC UA server and a handler process got callbacks to functions to handle special events. I will instantiate multiple nodes on the running server, if one callback is triggered by the handler process. To this point all of that works flawless, I create the instantiate the node like this:

self.object = self.server.get_objects_node().add_object(self.namespace_index, self.name ,self.type_id)

The add_object function returns the created object but if I access the server with a client there is no new object (If I call it from the same process the object is created with out a problem). Has anyone had a similar problem and know how to solve it ?

zerox1212 commented 5 years ago

Like I was getting at before, call instantiate() to create an instance of a custom object.

See example here: https://github.com/FreeOpcUa/python-opcua/blob/master/examples/server-instantiate-object.py

Lukas1811 commented 5 years ago

The add_object() function only calls the create_object() function which also use the instantiate() function, in the end there is no difference. I also tested it with the instantiate() function and it doesn't work.

def create_object(parent, nodeid, bname, objecttype=None):
    """
    create a child node object
    arguments are nodeid, browsename, [objecttype]
    or namespace index, name, [objecttype]
    if objectype is given (a NodeId) then the type node is instantiated inclusive its child nodes
    """
    nodeid, qname = _parse_nodeid_qname(nodeid, bname)
    if objecttype is not None:
        objecttype = node.Node(parent.server, objecttype)
        dname = ua.LocalizedText(qname.Name)
        nodes = instantiate(parent, objecttype, nodeid, bname=qname, dname=dname)[0]
        return nodes
    else:
        return node.Node(parent.server, _create_object(parent.server, parent.nodeid, nodeid, qname, ua.ObjectIds.BaseObjectType))
zerox1212 commented 5 years ago

I do not think this library is well tested in a multiprocess environment. I don't know your application, but do you really need multiple processes for OPC UA?

I suppose the issue is related to a Python process having a copy of the main process memory and all nodes of the server being held in a dict. A standard dict can't be used across processes with out having a Manager() I think? At any rate, adapting your code to call add_object on the server process will be much easier than supporting multiprocessing in this case.

oroulet commented 5 years ago

what do you mean by different processes? multiprocess module? threading? anyway the entire opcua server is in one thread and any client accessing it is also served in same thread. So unless you are doing sometthings strange it should work fine. and we donnot have enough info to help more

zerox1212 commented 5 years ago

I'm pretty sure he is handing python ua functions off to a process, that process will have a copy of the main process memory. When he calls add_object it's getting added to that processes' dict, not the dict in the server process. That is why a client can't see the object he created. The original process with the server is responding and his new object is in the dict of the other process.

Lukas1811 commented 5 years ago

@oroulet Yes im using multiprocessing to create the process

@zerox1212 I have also thought about that, I think threads wouldn't have this problem, only processes will have it due to there own memory, like you mentioned

jigar88 commented 3 years ago

I have tried to use multiprocessing and have the same issue , where it can't create a node on OPC server.