Pyro Flame is an easy way of exposing remote modules and builtins, and even a remote interactive Python console. It is available since Pyro 4.10. With Flame, you don’t need to write any server side code anymore, and still be able to call objects, modules and other things on the remote machine. Flame does this by giving a client direct access to any module or builtin that is available on the remote machine.
Flame can be found in the Pyro4.utils.flame module.
Warning
Be very sure about what you are doing before enabling Flame.
Flame is disabled by default. This is because it allows client programs full access to everything on your system. Only use it if you fully trust your environment and the clients that can connect to your machines.
(Flame is also symbolic for burning server machines that got totally owned by malicious clients.)
Flame is actually a special Pyro object that is exposed via a normal Pyro daemon. You need to start it explicitly in your daemon. This is done by calling a utility function with your daemon that you want to enable flame on:
import Pyro4.utils.flame
Pyro4.utils.flame.start(daemon)
There’s a little command line server program that will launch a flame enabled Pyro daemon, to avoid the hassle of having to write a custom server program yourself everywhere you want to provide a Flame server:
python -m Pyro4.utils.flameserver
The command line arguments are similar to the echo server (see Test echo server). Use -h to make it print a short help text.
A Flame server exposes a "Pyro.Flame" object (you can hardcode this name or use the constant Pyro4.constants.FLAME_NAME). Its interface is described in the API documentation, see Pyro4.utils.flame.Flame.
Connecting to the flame server can be done as usual (by creating a Pyro proxy yourself) or by using the convenience function Pyro4.utils.flame.connect(). A little example follows. You need to run a flame server running, then you can write a client like this:
import Pyro4.utils.flame
flame = Pyro4.utils.flame.connect("hostname:9999") # or whatever the server runs at
socketmodule = flame.module("socket")
osmodule = flame.module("os")
print "remote host name=", socketmodule.gethostname()
print "remote server directory contents=", osmodule.listdir(".")
flame.execute("import math")
root = flame.evaluate("math.sqrt(500)")
print "calculated square root=", root
print "remote exceptions also work", flame.evaluate("1//0")
# print something on the remote std output
flame.builtin("print")("Hello there, remote server stdout!")
A remote interactive console can be started like this:
with flame.console() as console:
console.interact()
# ... you can repeat sessions if you want
... which will print something like:
Python 2.7.2 (default, Jun 12 2011, 20:46:48)
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
(Remote console on charon:9999)
>>> # type stuff here and it gets executed on the remote machine
>>> import socket
>>> socket.gethostname()
'charon.local'
>>> ^D
(Remote session ended)
Note
The getfile and sendfile functions can be used for very basic file transfer.
The getmodule and sendmodule functions can be used to send module source files to other machines so it is possible to execute code that wasn’t available before. This is a very experimental replacement of the mobile code feature that Pyro 3.x had. It also is a very easy way of totally owning the server because you can make it execute anything you like. Be very careful.
Note
Pyrolite - client library for Java and .NET also supports convenient access to a Pyro Flame server. This includes the remote interactive console.
See the flame example for example code including uploading module source code to the server.