def main(): config = configparser.ConfigParser() # does not throw an error, just returns the empty set if the file doesn't exist config.read(CONFIG.BASEPATH + '/config/iGrill_config.ini') loglevel = config.get("Logging", "LogLevel", fallback="Error") logfile = config.get("Logging", "LogFile", fallback="") parser = argparse.ArgumentParser( description='Runs a thread to control the buzzer') parser.add_argument('-l', '--log-level', action='store', dest='log_level', default=loglevel, help='Set log level, default: \'' + loglevel + '\'') parser.add_argument('-d', '--log-destination', action='store', dest='log_destination', default=logfile, help='Set log destination (file), default: \'' + logfile + '\'') options = parser.parse_args() SetupLog(options.log_level, options.log_destination) daemon = Daemon(host=BUZZ.DAEMON.PYRO_HOST, port=BUZZ.DAEMON.PYRO_PORT) buzzObj = Buzzer(daemon) uri = daemon.register(buzzObj, objectId=BUZZ.DAEMON.PYRO_OBJECT_ID) logging.debug(uri) daemon.requestLoop() logging.debug('exited requestLoop') daemon.shutdown() daemon.close() logging.debug('daemon closed') sys.exit(buzzObj.ExitCode())
def run_maestral_daemon(config_name="maestral", run=True, log_to_stdout=False): """ Wraps :class:`maestral.main.Maestral` as Pyro daemon object, creates a new instance and start Pyro's event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. This command will return silently if the daemon is already running. :param str config_name: The name of the Maestral configuration to use. :param bool run: If ``True``, start syncing automatically. Defaults to ``True``. :param bool log_to_stdout: If ``True``, write logs to stdout. Defaults to ``False``. """ from maestral.main import Maestral sock_name = sockpath_for_config(config_name) pid_name = pidpath_for_config(config_name) lockfile = PIDLockFile(pid_name) # acquire PID lock file try: lockfile.acquire(timeout=1) except AlreadyLocked: if is_pidfile_stale(lockfile): lockfile.break_lock() else: logger.debug(f"Maestral already running") return logger.debug(f"Starting Maestral daemon on socket '{sock_name}'") try: # clean up old socket, create new one try: os.remove(sock_name) except FileNotFoundError: pass daemon = Daemon(unixsocket=sock_name) # start Maestral as Pyro server ExposedMaestral = expose(Maestral) # mark stop_sync and shutdown_daemon as oneway methods # so that they don't block on call ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.shutdown_pyro_daemon = oneway( ExposedMaestral.shutdown_pyro_daemon) m = ExposedMaestral(config_name, run=run, log_to_stdout=log_to_stdout) daemon.register(m, f"maestral.{config_name}") daemon.requestLoop(loopCondition=m._loop_condition) daemon.close() except Exception: traceback.print_exc() finally: # remove PID lock lockfile.release()
def setUp(self): self.m_daemon = Daemon(host=BUZZ.DAEMON.PYRO_HOST, port=BUZZ.DAEMON.PYRO_PORT) with mock.patch('pygrill.board.buzzer_daemon.pigpio.pi') as mockitem: self.m_mock_inst = mockitem.return_value self.m_buzzDaemon = buzzer_daemon.Buzzer(self.m_daemon, boardIn=SSRC.BOARD.REV_sD) self.m_daemon.register(self.m_buzzDaemon, objectId=BUZZ.DAEMON.PYRO_OBJECT_ID)
def setUp(self): self.m_daemon = Daemon(host=KASA.DAEMON.PYRO_HOST, port=KASA.DAEMON.PYRO_PORT) # This must be scoped oddly. Daemon uses sockets so we don't want to mock the socket # object untill the daemon is setup. with mock.patch('pygrill.kasa.kasa_daemon.socket.socket') as mockitem: self.m_mock_inst = mockitem.return_value self.m_mock_inst.recvfrom.return_value = [kasa_daemon.Encrypt( TEST.KASA.DAEMON.DISCOVER_RSP), ['192.168.0.0', 9999]] self.m_mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.DISCOVER_RSP) self.m_kasaDaemon = kasa_daemon.Kasa(self.m_daemon) self.m_daemon.register( self.m_kasaDaemon, objectId=KASA.DAEMON.PYRO_OBJECT_ID)
def threadAlert(stock, homeBroker): global option, running, ordemFinalizada with Daemon() as daemon2: homeBroker._pyroClaimOwnership() callback = CallbackHandler() daemon2.register(callback) worker = homeBroker.createWorker( callback) #Cria worker no servidor para verificar preço da ação worker.addStockToAlert(stock) print("Alerta criado com sucesso!") ordemFinalizada = 1 daemon2.requestLoop( loopCondition=lambda: CallbackHandler.workdone != True) CallbackHandler.workdone = False
def main(args): if len(args) != 3: print("usage: client.py <robotname> <robottype>") print(" type is one of: %s" % list(observers.keys())) return name = args[1] observertype = args[2] with Daemon() as daemon: observer = observers[observertype]() daemon.register(observer) gameserver = Proxy("PYRONAME:example.robotserver") robot = gameserver.register(name, observer) with robot: # make sure it disconnects, before the daemon thread uses it later robot.emote("Hi there! I'm here to kick your ass") observer.robot = robot print("Pyro server registered on %s" % daemon.locationStr) daemon.requestLoop()
def threadExecuteOrder(order, homeBroker): global option, running, ordemFinalizada with Daemon() as daemon1: homeBroker._pyroClaimOwnership() callback = CallbackHandler() daemon1.register(callback) worker = homeBroker.createWorker( callback) #Cria worker no servidor para tentar executar a ordem worker.tryExecuteOrder(order) print("Ordem enviada com sucesso!") ordemFinalizada = 1 daemon1.requestLoop( loopCondition=lambda: CallbackHandler.workdone != True) CallbackHandler.workdone = False
def main(): gui = PyroGUI() # create a pyro daemon with object daemon = Daemon() obj = MessagePrinter(gui) uri = daemon.register(obj, "pyrogui.message") gui.add_message("Pyro server started. Not using threads.") gui.add_message("Use the command line client to send messages.") urimsg = "Pyro object uri = {0}".format(uri) gui.add_message(urimsg) print(urimsg) # add a Pyro event callback to the gui's mainloop gui.install_pyro_event_callback(daemon) # enter the mainloop gui.mainloop()
def testSerializePyroTypes(self): uri = URI("PYRO:obj@host:9999") ser = self.serializer.dumps(uri) uri2 = self.serializer.loads(ser) assert isinstance(uri2, URI) assert uri2 == uri proxy = Proxy("PYRO:obj@host:9999") proxy._pyroHandshake = "handshake" ser = self.serializer.dumps(proxy) proxy2 = self.serializer.loads(ser) assert isinstance(proxy2, Proxy) assert proxy2 == proxy assert proxy2._pyroHandshake == "handshake" with Daemon(host="localhost", port=12345, nathost="localhost", natport=9876) as daemon: ser = self.serializer.dumps(daemon) daemon2 = self.serializer.loads(ser) assert isinstance(daemon2, Daemon)
def run(self): daemon = Daemon() obj = MessagePrinter(self.gui) self.uri = daemon.register(obj, "pyrogui.message2") self.started.set() daemon.requestLoop()
import time from Pyro5.api import expose, Daemon print("Autoreconnect using PYRO uri.") @expose class TestClass(object): def method(self, arg): print("Method called with %s" % arg) print("You can now try to stop this server with ctrl-C/ctrl-Break") time.sleep(1) # We are responsible to (re)connect objects with the same object Id, # so that the client can reuse its PYRO-uri directly to reconnect. # There are a few options, such as depending on the Name server to # maintain a name registration for our object (see the serverNS for this). # Or we could store our objects in our own persistent database. # But for this example we will just use a pre-generated id (fixed name). # The other thing is that your Daemon must re-bind on the same port. # By default Pyro will select a random port so we specify a fixed port. with Daemon(port=7777) as daemon: uri = daemon.register(TestClass, objectId="example.autoreconnect_fixed_objectid") print("Server started, uri: %s" % uri) daemon.requestLoop()
import time from Pyro5.api import expose, locate_ns, Daemon, config @expose class TimeoutServer(object): def delay(self, amount): print("sleeping %d" % amount) time.sleep(amount) print("done.") return "slept %d seconds" % amount config.COMMTIMEOUT = 0 # the server won't be using timeouts ns = locate_ns() daemon = Daemon() daemon2 = Daemon() obj = TimeoutServer() obj2 = TimeoutServer() uri = daemon.register(obj) uri2 = daemon2.register(obj2) ns.register("example.timeout", uri) ns.register("example.timeout.frozendaemon", uri2) print("Server ready.") # Note that we're only starting one of the 2 daemons. # daemon2 is not started, to simulate connection timeouts. daemon.requestLoop()
help="hostname to bind server on") parser.add_option("-p", "--port", dest="port", type="int", default=0, help="port to bind server on (0=random)") parser.add_option("-u", "--unixsocket", help="Unix domain socket name to bind server on") parser.add_option("-s", "--storage", dest="storage", type="choice", choices=["sqlite", "memory"], default="sqlite", help="storage type (default=%default)") options, args = parser.parse_args() make_messagebus.storagetype = options.storage daemon = Daemon(host=options.host, port=options.port, unixsocket=options.unixsocket) uri = daemon.register(MessageBus) print("Pyro Message Bus.") print(" uri =", uri) ns = locate_ns() ns.register(PYRO_MSGBUS_NAME, uri) print(" name =", PYRO_MSGBUS_NAME) print("Server running, storage is {}.".format(make_messagebus.storagetype)) daemon.requestLoop()
from Pyro5.api import Daemon, serve import excep def my_error_handler(daemon, client_sock, method, vargs, kwargs, exception): print("\nERROR IN METHOD CALL USER CODE:") print(" client={} method={} exception={}".format(client_sock, method.__qualname__, repr(exception))) daemon = Daemon() daemon.methodcall_error_handler = my_error_handler serve({excep.TestClass: "example.exceptions"}, daemon=daemon, use_ns=True, verbose=True)
#!/usr/bin/env python3 """Daemon.""" from Pyro5.api import Daemon, expose, behavior, serve, current_context, oneway from gpio_led import LEDPanel @expose @behavior(instance_mode="single") class Photobooth(object): """Photobooth daemon.""" def __init__(self): self.ledPanelCtl = None @oneway def ledCtl(self, action, resume, brightness, kwargs): if not self.ledPanelCtl: self.ledPanelCtl = LEDPanel().get_effects() self.ledPanelCtl.abort() self.ledPanelCtl.run(action, resume, brightness, kwargs) if __name__ == "__main__": daemon = Daemon(host="localhost", port=9090) uri = daemon.register(Photobooth, 'ledpanel.control') daemon.requestLoop()
@expose def factorize(self, n): print("factorize request received for", n) result = self._factorize(n) print(" -->", result) return result def _factorize(self, n): """simple algorithm to find the prime factorials of the given number n""" def isPrime(n): return not any(x for x in range(2, int(sqrt(n)) + 1) if n % x == 0) primes = [] candidates = range(2, n + 1) candidate = 2 while not primes and candidate in candidates: if n % candidate == 0 and isPrime(candidate): primes = primes + [candidate] + self._factorize(n // candidate) candidate += 1 return primes with Daemon(host=Pyro5.socketutil.get_ip_address(None)) as daemon: # create a unique name for this worker (otherwise it overwrites other workers in the name server) worker_name = "Worker_%d@%s" % (os.getpid(), socket.gethostname()) print("Starting up worker", worker_name) uri = daemon.register(Worker) with locate_ns() as ns: ns.register(worker_name, uri, metadata={"example3.worker.factorizer"}) daemon.requestLoop()
def run(self): with Daemon() as daemon: daemon.register(self.chatter) daemon.requestLoop(lambda: not self.chatter.abort)
import time from Pyro5.api import expose, Daemon print("Autoreconnect using PYRO uri.") @expose class TestClass(object): def method(self, arg): print("Method called with %s" % arg) print("You can now try to stop this server with ctrl-C/ctrl-Break") time.sleep(1) # We are responsible to (re)connect objects with the same object Id, # so that the client can reuse its PYRO-uri directly to reconnect. # There are a few options, such as depending on the Name server to # maintain a name registration for our object (see the serverNS for this). # Or we could store our objects in our own persistent database. # But for this example we will just use a pre-generated id (fixed name). # The other thing is that your Daemon must re-bind on the same port. # By default Pyro will select a random port so we specify a fixed port. with Daemon(port=3002) as daemon: uri = daemon.register(TestClass, objectId="example.autoreconnect_fixed_objectid") print("Server started, uri: %s" % uri) daemon.requestLoop()
z = complex(zr, zi) c = z for iters in range(self.maxiters + 1): if z.real * z.real + z.imag * z.imag > 4: # abs(z) > 2 break z = z * z + c if iters >= self.maxiters: return 0, 0, 0 abs_z = math.sqrt(z.real * z.real + z.imag * z.imag) # abs(z) r = (iters + 32) % 255 g = (iters - math.log(abs_z)) % 255 b = (abs_z * iters) % 255 return int(r), int(g), int(b) if __name__ == "__main__": with Daemon() as d: uri_1 = d.register(Mandelbrot) uri_2 = d.register(MandelbrotColorPixels) with locate_ns() as ns: ns.register(Mandelbrot._pyroId, uri_1, safe=True, metadata={"class:mandelbrot_calc"}) ns.register(MandelbrotColorPixels._pyroId, uri_2, safe=True, metadata={"class:mandelbrot_calc_color"}) print("Mandelbrot calculation server ready.") d.requestLoop()
def start_maestral_daemon(config_name: str = "maestral", log_to_stdout: bool = False, start_sync: bool = False) -> None: """ Starts the Maestral daemon with event loop in the current thread. Startup is race free: there will never be two daemons running for the same config. Wraps :class:`main.Maestral` as Pyro daemon object, creates a new instance and starts an asyncio event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. When this function is called from the main thread on macOS, the asyncio event loop uses Cocoa's CFRunLoop to process event. This allows integration with Cocoa frameworks which use callbacks to process use input such as clicked notifications, etc, and potentially allows showing a GUI. :param config_name: The name of the Maestral configuration to use. :param log_to_stdout: If ``True``, write logs to stdout. :param start_sync: If ``True``, start syncing once the daemon has started. :raises: :class:`RuntimeError` if a daemon for the given ``config_name`` is already running. """ import asyncio from maestral.main import Maestral if threading.current_thread() is not threading.main_thread(): raise RuntimeError("Must run daemon in main thread") # acquire PID lock file lock = maestral_lock(config_name) if not lock.acquire(): raise RuntimeError("Maestral daemon is already running") # Nice ourselves to give other processes priority. We will likely only # have significant CPU usage in case of many concurrent downloads. os.nice(10) # catch sigterm and shut down gracefully signal.signal(signal.SIGTERM, _sigterm_handler) # integrate with CFRunLoop in macOS, only works in main thread if sys.platform == "darwin": logger.debug("Cancelling all tasks from asyncio event loop") from rubicon.objc.eventloop import EventLoopPolicy # type: ignore # clean up any pending tasks before we change the event loop policy # this is necessary if previous code has run an asyncio loop loop = asyncio.get_event_loop() try: # Python 3.7 and higher all_tasks = asyncio.all_tasks(loop) except AttributeError: # Python 3.6 all_tasks = asyncio.Task.all_tasks(loop) pending_tasks = [t for t in all_tasks if not t.done()] for task in pending_tasks: task.cancel() loop.run_until_complete( asyncio.gather(*pending_tasks, return_exceptions=True)) loop.close() logger.debug("Integrating with CFEventLoop") # set new event loop policy asyncio.set_event_loop_policy(EventLoopPolicy()) # get the default event loop loop = asyncio.get_event_loop() sd_notifier = sdnotify.SystemdNotifier() # notify systemd that we have started if NOTIFY_SOCKET: logger.debug("Running as systemd notify service") logger.debug("NOTIFY_SOCKET = %s", NOTIFY_SOCKET) sd_notifier.notify("READY=1") # notify systemd periodically if alive if IS_WATCHDOG and WATCHDOG_USEC: async def periodic_watchdog() -> None: if WATCHDOG_USEC: sleep = int(WATCHDOG_USEC) while True: sd_notifier.notify("WATCHDOG=1") await asyncio.sleep(sleep / (2 * 10**6)) logger.debug("Running as systemd watchdog service") logger.debug("WATCHDOG_USEC = %s", WATCHDOG_USEC) logger.debug("WATCHDOG_PID = %s", WATCHDOG_PID) loop.create_task(periodic_watchdog()) # get socket for config name sockpath = sockpath_for_config(config_name) logger.debug(f"Socket path for '{config_name}' daemon: '{sockpath}'") # clean up old socket try: os.remove(sockpath) except FileNotFoundError: pass # expose maestral as Pyro server # convert management methods to one way calls so that they don't block logger.debug("Creating Pyro daemon") ExposedMaestral = expose(Maestral) ExposedMaestral.start_sync = oneway(ExposedMaestral.start_sync) ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.pause_sync = oneway(ExposedMaestral.pause_sync) ExposedMaestral.resume_sync = oneway(ExposedMaestral.resume_sync) ExposedMaestral.shutdown_daemon = oneway(ExposedMaestral.shutdown_daemon) maestral_daemon = ExposedMaestral(config_name, log_to_stdout=log_to_stdout) if start_sync: logger.debug("Starting sync") maestral_daemon.start_sync() try: logger.debug("Starting event loop") with Daemon(unixsocket=sockpath) as daemon: daemon.register(maestral_daemon, f"maestral.{config_name}") for socket in daemon.sockets: loop.add_reader(socket.fileno(), daemon.events, daemon.sockets) loop.run_until_complete(maestral_daemon.shutdown_complete) for socket in daemon.sockets: loop.remove_reader(socket.fileno()) except Exception: traceback.print_exc() finally: if NOTIFY_SOCKET: # notify systemd that we are shutting down sd_notifier.notify("STOPPING=1")
import os from Pyro5.api import expose, Daemon @expose class Thingy(object): def message(self, arg): print("Message received:", arg) return "Roger!" if os.path.exists("example_unix.sock"): os.remove("example_unix.sock") with Daemon(unixsocket="example_unix.sock") as d: uri = d.register(Thingy, "example.unixsock") print("Server running, uri=", uri) d.requestLoop()
def start_maestral_daemon(config_name: str = "maestral", log_to_stderr: bool = False, start_sync: bool = False) -> None: """ Starts the Maestral daemon with event loop in the current thread. Startup is race free: there will never be more than one daemon running with the same config name. The daemon is a :class:`maestral.main.Maestral` instance which is exposed as Pyro daemon object and listens for requests on a unix domain socket. This call starts an asyncio event loop to process client requests and blocks until the event loop shuts down. On macOS, the event loop is integrated with Cocoa's CFRunLoop. This allows processing Cocoa events and callbacks, for instance for desktop notifications. :param config_name: The name of the Maestral configuration to use. :param log_to_stderr: If ``True``, write logs to stderr. :param start_sync: If ``True``, start syncing once the daemon has started. If the ``start_sync`` call fails, an error will be logged but not raised. :raises RuntimeError: if a daemon for the given ``config_name`` is already running. """ import asyncio from .main import Maestral from .logging import scoped_logger, setup_logging setup_logging(config_name, log_to_stderr) dlogger = scoped_logger(__name__, config_name) dlogger.info("Starting daemon") if threading.current_thread() is not threading.main_thread(): dlogger.error("Must run daemon in main thread") raise RuntimeError("Must run daemon in main thread") dlogger.debug("Environment:\n%s", pformat(os.environ.copy())) # acquire PID lock file lock = maestral_lock(config_name) if lock.acquire(): dlogger.debug("Acquired daemon lock: %s", lock.path) else: dlogger.error("Could not acquire lock, daemon is already running") raise RuntimeError("Daemon is already running") # Nice ourselves to give other processes priority. os.nice(10) # Integrate with CFRunLoop in macOS. if IS_MACOS: dlogger.debug("Integrating with CFEventLoop") from rubicon.objc.eventloop import EventLoopPolicy # type: ignore asyncio.set_event_loop_policy(EventLoopPolicy()) # Get the default event loop. loop = asyncio.get_event_loop() sd_notifier = sdnotify.SystemdNotifier() # Notify systemd that we have started. if NOTIFY_SOCKET: dlogger.debug("Running as systemd notify service") dlogger.debug("NOTIFY_SOCKET = %s", NOTIFY_SOCKET) sd_notifier.notify("READY=1") # Notify systemd periodically if alive. if IS_WATCHDOG and WATCHDOG_USEC: async def periodic_watchdog() -> None: if WATCHDOG_USEC: sleep = int(WATCHDOG_USEC) while True: sd_notifier.notify("WATCHDOG=1") await asyncio.sleep(sleep / (2 * 10**6)) dlogger.debug("Running as systemd watchdog service") dlogger.debug("WATCHDOG_USEC = %s", WATCHDOG_USEC) dlogger.debug("WATCHDOG_PID = %s", WATCHDOG_PID) loop.create_task(periodic_watchdog()) # Get socket for config name. sockpath = sockpath_for_config(config_name) dlogger.debug(f"Socket path: '{sockpath}'") # Clean up old socket. try: os.remove(sockpath) except FileNotFoundError: pass # Expose maestral as Pyro server. Convert management # methods to one way calls so that they don't block. dlogger.debug("Creating Pyro daemon") ExposedMaestral = expose(Maestral) ExposedMaestral.start_sync = oneway(ExposedMaestral.start_sync) ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.shutdown_daemon = oneway(ExposedMaestral.shutdown_daemon) maestral_daemon = ExposedMaestral(config_name, log_to_stderr=log_to_stderr) if start_sync: dlogger.debug("Starting sync") maestral_daemon.start_sync() try: dlogger.debug("Starting event loop") with Daemon(unixsocket=sockpath) as daemon: daemon.register(maestral_daemon, f"maestral.{config_name}") # Reduce Pyro's housekeeping frequency from 2 sec to 20 sec. # This avoids constantly waking the CPU when we are idle. if daemon.transportServer.housekeeper: daemon.transportServer.housekeeper.waittime = 20 for socket in daemon.sockets: loop.add_reader(socket.fileno(), daemon.events, daemon.sockets) # Handle sigterm gracefully. signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGINT) for s in signals: loop.add_signal_handler(s, maestral_daemon.shutdown_daemon) loop.run_until_complete(maestral_daemon.shutdown_complete) for socket in daemon.sockets: loop.remove_reader(socket.fileno()) # Prevent Pyro housekeeping from blocking shutdown. daemon.transportServer.housekeeper = None except Exception as exc: dlogger.error(exc.args[0], exc_info=True) finally: if NOTIFY_SOCKET: # Notify systemd that we are shutting down. sd_notifier.notify("STOPPING=1")
def main(log_to_file=True): import pkg_resources version = pkg_resources.require('humidifier-controller')[0].version print('Starting Humidifier Controller Server, version: ' + version) config.SERVERTYPE = 'multiplex' daemon = Daemon() def start_client_logger(): from threading import Thread t = Thread(target=Logger, kwargs={'log_to_file': log_to_file}, daemon=True) t.start() return t def signal_handler(signo, frame): if daemon != None: daemon.transportServer.shutting_down = True print(f'Shutting down gracefully exit code: {signo}') daemon.shutdown() from threading import enumerate logger_threads = [ thread for thread in enumerate() if isinstance(thread, Logger) ] for logger_thread in logger_threads: print("Stopping {}.".format(logger_thread)) logger_thread.stop() sys.exit(1) import signal for sig in ('TERM', 'HUP', 'INT'): signal.signal(getattr(signal, 'SIG' + sig), signal_handler) nameserverDaemon = None try: nameserverUri, nameserverDaemon, broadcastServer = start_ns() assert broadcastServer is not None, "expect a broadcast server to be created" print("got a Nameserver, uri=%s" % nameserverUri) except OSError: print('Pyro nameserver already running. No idea who started it.') if (nameserverDaemon == None): with locate_ns() as ns: try: ns.lookup('serial_server.serial_connection') print("Serial server is already registered. Aborting.") return 0 except: pass serial_connection = SerialConnection(baudrate='9600') serial_connection.set_settings(serial_connection.read_settings()) serial_connection.post_message('\0') serial_uri = daemon.register(serial_connection) if (nameserverDaemon == None): with locate_ns() as ns: ns.register('serial_server.serial_connection', serial_uri) else: nameserverDaemon.nameserver.register('serial_server.serial_connection', serial_uri) daemon.combine(nameserverDaemon) daemon.combine(broadcastServer) print('Serial connection registered.') start_client_logger() daemon.requestLoop()
from Pyro5.api import expose, Daemon, Proxy # create our own socket pair (server-client sockets that are already connected) sock1, sock2 = socket.socketpair() class Echo(object): @expose def echo(self, message): print("server got message: ", message) return "thank you" # create a daemon with some Pyro objectrunning on our custom server socket daemon = Daemon(connected_socket=sock1) daemon.register(Echo, "echo") print("(Pyro daemon running on", daemon.locationStr, ")\n") daemonthread = threading.Thread(target=daemon.requestLoop) daemonthread.daemon = True daemonthread.start() # create a client running on the client socket with Proxy("echo", connected_socket=sock2) as p: reply = p.echo("hello!") print("client got reply:", reply) reply = p.echo("hello again!") print("client got reply:", reply) with Proxy("echo", connected_socket=sock2) as p: reply = p.echo("hello2!")
def run_maestral_daemon(config_name='maestral', run=True, log_to_stdout=False): """ Wraps :class:`maestral.main.Maestral` as Pyro daemon object, creates a new instance and start Pyro's event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. This command will return silently if the daemon is already running. :param str config_name: The name of the Maestral configuration to use. :param bool run: If ``True``, start syncing automatically. Defaults to ``True``. :param bool log_to_stdout: If ``True``, write logs to stdout. Defaults to ``False``. """ import threading from maestral.main import Maestral sock_name = sockpath_for_config(config_name) pid_name = pidpath_for_config(config_name) lockfile = PIDLockFile(pid_name) if threading.current_thread() is threading.main_thread(): signal.signal(signal.SIGTERM, _sigterm_handler) # acquire PID lock file try: lockfile.acquire(timeout=1) except (AlreadyLocked, LockTimeout): if is_pidfile_stale(lockfile): lockfile.break_lock() else: logger.debug(f'Maestral already running') return # Nice ourselves give other processes priority. We will likely only # have significant CPU usage in case of many concurrent downloads. os.nice(10) logger.debug(f'Starting Maestral daemon on socket "{sock_name}"') try: # clean up old socket try: os.remove(sock_name) except FileNotFoundError: pass daemon = Daemon(unixsocket=sock_name) # start Maestral as Pyro server ExposedMaestral = expose(Maestral) # mark stop_sync and shutdown_daemon as one way # methods so that they don't block on call ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.pause_sync = oneway(ExposedMaestral.pause_sync) ExposedMaestral.shutdown_pyro_daemon = oneway( ExposedMaestral.shutdown_pyro_daemon) m = ExposedMaestral(config_name, run=run, log_to_stdout=log_to_stdout) daemon.register(m, f'maestral.{config_name}') daemon.requestLoop(loopCondition=m._loop_condition) daemon.close() except Exception: traceback.print_exc() except (KeyboardInterrupt, SystemExit): logger.info('Received system exit') sys.exit(0) finally: lockfile.release()
# this only works on Linux # it uses the abstract namespace socket feature. from Pyro5.api import expose, Daemon @expose class Thingy(object): def message(self, arg): print("Message received:", arg) return "Roger!" with Daemon(unixsocket="\0example_unix.sock" ) as d: # notice the 0-byte at the start uri = d.register(Thingy, "example.unixsock") print("Server running, uri=", uri) string_uri = str(uri) print( "Actually, the uri contains a 0-byte, make sure you copy the part between the quotes to the client:" ) print(repr(string_uri)) d.requestLoop()
import os from Pyro5.api import expose, Daemon class QuoteGen(object): @expose def quote(self): try: quote = os.popen('fortune').read() if len(quote) > 0: return quote return "This system cannot provide you a good fortune, install 'fortune'" except: return "This system knows no witty quotes :-(" with Daemon() as daemon: quote1 = QuoteGen() quote2 = QuoteGen() uri1 = daemon.register(quote1) # let Pyro create a unique name for this one uri2 = daemon.register(quote2, "example.quotegen") # provide a logical name ourselves print("QuoteGen is ready, not using the Name Server.") print("You can use the following two URIs to connect to me:") print(uri1) print(uri2) daemon.requestLoop()
self._symbols = symbols def quotes(self): while True: symbol = random.choice(self.symbols) yield symbol, round(random.uniform(5, 150), 2) time.sleep(random.random() / 2.0) @property def name(self): return self._name @property def symbols(self): return self._symbols if __name__ == "__main__": nasdaq = StockMarket("NASDAQ", ["AAPL", "CSCO", "MSFT", "GOOG"]) newyork = StockMarket("NYSE", ["IBM", "HPQ", "BP"]) # Add the proper "host" and "port" arguments for the construction # of the Daemon so it can be accessed remotely with Daemon(host=HOST_IP, port=HOST_PORT) as daemon: nasdaq_uri = daemon.register(nasdaq) newyork_uri = daemon.register(newyork) with locate_ns() as ns: ns.register("example.stockmarket.nasdaq", nasdaq_uri) ns.register("example.stockmarket.newyork", newyork_uri) print("Stockmarkets available.") daemon.requestLoop()
from Pyro5.api import locate_ns, Daemon, type_meta, Proxy from resources import LaserPrinter, MatrixPrinter, PhotoPrinter, TapeStorage, DiskStorage, Telephone, Faxmachine # register various objects with some metadata describing their resource class ns = locate_ns() d = Daemon() uri = d.register(LaserPrinter) ns.register("example.resource.laserprinter", uri, metadata=type_meta(LaserPrinter) | {"resource:printer", "performance:fast"}) uri = d.register(MatrixPrinter) ns.register("example.resource.matrixprinter", uri, metadata=type_meta(MatrixPrinter) | {"resource:printer", "performance:slow"}) uri = d.register(PhotoPrinter) ns.register("example.resource.photoprinter", uri, metadata=type_meta(PhotoPrinter) | {"resource:printer", "performance:slow"}) uri = d.register(TapeStorage) ns.register("example.resource.tapestorage", uri, metadata=type_meta(TapeStorage) | {"resource:storage", "performance:slow"}) uri = d.register(DiskStorage) ns.register("example.resource.diskstorage", uri, metadata=type_meta(DiskStorage)
# If we KNOW 100% that PYRONAME-uris are the only thing used to access our # object, we could skip all this and just register as usual. # That works because the proxy, when reconnecting, will do a new nameserver lookup # and receive the new object uri back. This REQUIRES: # - clients will never connect using a PYRO-uri # - client proxy._pyroBind() is never called # BUT for sake of example, and because we really cannot guarantee the above, # here we go for the safe route and reuse our previous object id. ns = locate_ns() try: existing = ns.lookup("remote") print("Object still exists in Name Server with id: %s" % existing.object) print("Previous daemon socket port: %d" % existing.port) # start the daemon on the previous port daemon = Daemon(port=existing.port) # register the object in the daemon with the old objectId daemon.register(TestClass, objectId=existing.object) except Pyro5.errors.NamingError: print("There was no previous registration in the name server.") # just start a new daemon on a random port daemon = Daemon() # register the object in the daemon and let it get a new objectId # also need to register in name server because it's not there yet. uri = daemon.register(TestClass) ns.register("remote2", uri) print("Server started.") daemon.requestLoop() # note: we are not removing the name server registration when terminating!