Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions source/wrappers/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ install( FILES ${INSTALL_FILES} DESTINATION python_installer/pyuda )
configure_file( ${CMAKE_CURRENT_LIST_DIR}/pyuda/_version.py.in ${CMAKE_CURRENT_BINARY_DIR}/pyuda/_version.py @ONLY )
install( FILES ${CMAKE_CURRENT_BINARY_DIR}/pyuda/_version.py DESTINATION python_installer/pyuda )

file( GLOB EXAMPLE_SCRIPTS examples/*.py )
install( FILES ${EXAMPLE_SCRIPTS} DESTINATION python_installer/examples )
file( GLOB DEV_TEST_SCRIPTS devscripts/*.py )
install( FILES ${DEV_TEST_SCRIPTS} DESTINATION python_installer/devscripts )

### extra install steps for the dummy "uda" repo which will mirror "pyuda" on pypi
set( DUMMY_REPO_FILES
uda/README.md
Expand Down
46 changes: 46 additions & 0 deletions source/wrappers/python/examples/parallel_client_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pyuda
import multiprocessing as mp
from enum import Enum, auto
from collections import namedtuple

ConnectionDetails = namedtuple('ConnectionDetails', ['name', 'port'])
RequestData = namedtuple('RequestData', ['signal', 'source'])
client = pyuda.Client()

class Result(Enum):
SOME = auto()
ERROR = auto()


def task(queue: mp.Queue, server: ConnectionDetails, request: RequestData):
# move client instantiation here to avoid errors
# client = pyuda.Client()
pyuda.Client.port = server.port
pyuda.Client.server = server.name

try:
result = client.get(*request)
queue.put((Result.SOME, result))
except Exception as e:
queue.put((Result.ERROR, e))


def main():
server = ConnectionDetails("uda2.mast.l", 56565)
request = RequestData("help::help()", "")

# No error if start method is "spawn" or if client is only
# instantiated in task (after fork)
mp.set_start_method('fork')
print("process start method is: " + mp.get_start_method())

results_q = mp.Queue()
p = mp.Process(target=task, args=(results_q, server, request))
p.start()
item = results_q.get()
print(item)
p.join()


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions source/wrappers/python/pyuda/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class Client(with_metaclass(ClientMeta, object)):
__metaclass__ = ClientMeta

def __init__(self, debug_level=logging.ERROR):
cpyuda.set_pid()

self.version = __version__
assert self.version == cpyuda.get_build_version().decode(), "mismatching pyuda and c-library versions"

Expand Down
14 changes: 14 additions & 0 deletions source/wrappers/python/pyuda/cpyuda/client.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#cython: language_level=3

import os
import numpy as np
cimport uda
cimport numpy as np
Expand All @@ -9,6 +10,7 @@ from libc.stdlib cimport malloc, free
from libc.string cimport strlen


_pid = None
_properties = {
"get_datadble": ("GET_DATA_DOUBLE", False),
"get_dimdble": ("GET_DIM_DOUBLE", False),
Expand Down Expand Up @@ -39,6 +41,12 @@ if PY_MAJOR_VERSION >= 3.0:
else:
Properties = type(b'Properties', (), {v[0]:k for k,v in _properties.items()})


def set_pid():
global _pid
_pid = os.getpid()


def set_property(prop_name, value):
if prop_name.lower() not in _properties:
raise ValueError('invalid property ' + prop_name)
Expand Down Expand Up @@ -98,6 +106,8 @@ def get_server_uuid():


def get_data(signal, source):
if _pid != os.getpid():
raise ClientException("Calling client from a process different to process in which library was initialised")
handle = uda.idamGetAPI(signal.encode(), source.encode())
cdef const char* err_msg
cdef int err_code
Expand All @@ -114,6 +124,8 @@ def get_data(signal, source):


def get_data_batch(signals, sources):
if _pid != os.getpid():
raise ClientException("Calling client from a process different to process in which library was initialised")
assert len(signals) == len(sources)
cdef const char** signals_array = <const char**>malloc(len(signals) * sizeof(char*))
cdef const char** sources_array = <const char**>malloc(len(sources) * sizeof(char*))
Expand Down Expand Up @@ -301,6 +313,8 @@ cdef put_string(const char* instruction, const char* data):


def put_data(instruction, data=None):
if _pid != os.getpid():
raise ClientException("Calling client from a process different to process in which library was initialised")
if isinstance(data, np.ndarray):
if np.PyArray_TYPE(data) not in (np.NPY_STRING, np.NPY_UNICODE):
return put_ndarray(instruction, data)
Expand Down
Loading