ipengine.py
193 lines
| 6.4 KiB
| text/x-python
|
PythonLexer
Brian E Granger
|
r1234 | #!/usr/bin/env python | ||
# encoding: utf-8 | ||||
"""Start the IPython Engine.""" | ||||
__docformat__ = "restructuredtext en" | ||||
#------------------------------------------------------------------------------- | ||||
# Copyright (C) 2008 The IPython Development Team | ||||
# | ||||
# Distributed under the terms of the BSD License. The full license is in | ||||
# the file COPYING, distributed as part of this software. | ||||
#------------------------------------------------------------------------------- | ||||
#------------------------------------------------------------------------------- | ||||
# Imports | ||||
#------------------------------------------------------------------------------- | ||||
# Python looks for an empty string at the beginning of sys.path to enable | ||||
# importing from the cwd. | ||||
import sys | ||||
sys.path.insert(0, '') | ||||
from optparse import OptionParser | ||||
Brian Granger
|
r1958 | import os | ||
Brian E Granger
|
r1234 | |||
from twisted.application import service | ||||
from twisted.internet import reactor | ||||
from twisted.python import log | ||||
from IPython.kernel.fcutil import Tub, UnauthenticatedTub | ||||
from IPython.kernel.core.config import config_manager as core_config_manager | ||||
from IPython.config.cutils import import_item | ||||
from IPython.kernel.engineservice import EngineService | ||||
Brian Granger
|
r1945 | |||
# Create various ipython directories if they don't exist. | ||||
# This must be done before IPython.kernel.config is imported. | ||||
from IPython.iplib import user_setup | ||||
Brian Granger
|
r2023 | from IPython.utils.genutils import get_ipython_dir, get_log_dir, get_security_dir | ||
Brian Granger
|
r1945 | if os.name == 'posix': | ||
rc_suffix = '' | ||||
else: | ||||
rc_suffix = '.ini' | ||||
user_setup(get_ipython_dir(), rc_suffix, mode='install', interactive=False) | ||||
get_log_dir() | ||||
get_security_dir() | ||||
Brian E Granger
|
r1234 | from IPython.kernel.config import config_manager as kernel_config_manager | ||
from IPython.kernel.engineconnector import EngineConnector | ||||
#------------------------------------------------------------------------------- | ||||
# Code | ||||
#------------------------------------------------------------------------------- | ||||
def start_engine(): | ||||
""" | ||||
Start the engine, by creating it and starting the Twisted reactor. | ||||
This method does: | ||||
* If it exists, runs the `mpi_import_statement` to call `MPI_Init` | ||||
* Starts the engine logging | ||||
* Creates an IPython shell and wraps it in an `EngineService` | ||||
* Creates a `foolscap.Tub` to use in connecting to a controller. | ||||
* Uses the tub and the `EngineService` along with a Foolscap URL | ||||
(or FURL) to connect to the controller and register the engine | ||||
with the controller | ||||
""" | ||||
kernel_config = kernel_config_manager.get_config_obj() | ||||
core_config = core_config_manager.get_config_obj() | ||||
Brian E Granger
|
r1324 | |||
Brian E Granger
|
r1234 | # Execute the mpi import statement that needs to call MPI_Init | ||
Brian E Granger
|
r1324 | global mpi | ||
Brian E Granger
|
r1234 | mpikey = kernel_config['mpi']['default'] | ||
mpi_import_statement = kernel_config['mpi'].get(mpikey, None) | ||||
if mpi_import_statement is not None: | ||||
try: | ||||
Brian E Granger
|
r1324 | exec mpi_import_statement in globals() | ||
Brian E Granger
|
r1234 | except: | ||
mpi = None | ||||
else: | ||||
Brian E Granger
|
r1335 | mpi = None | ||
Brian E Granger
|
r1234 | |||
# Start logging | ||||
logfile = kernel_config['engine']['logfile'] | ||||
if logfile: | ||||
logfile = logfile + str(os.getpid()) + '.log' | ||||
try: | ||||
openLogFile = open(logfile, 'w') | ||||
except: | ||||
openLogFile = sys.stdout | ||||
else: | ||||
openLogFile = sys.stdout | ||||
log.startLogging(openLogFile) | ||||
# Create the underlying shell class and EngineService | ||||
shell_class = import_item(core_config['shell']['shell_class']) | ||||
engine_service = EngineService(shell_class, mpi=mpi) | ||||
shell_import_statement = core_config['shell']['import_statement'] | ||||
if shell_import_statement: | ||||
try: | ||||
engine_service.execute(shell_import_statement) | ||||
except: | ||||
Vishal Vatsa
|
r1776 | log.msg("Error running import_statement: %s" % shell_import_statement) | ||
Brian E Granger
|
r1234 | |||
# Create the service hierarchy | ||||
main_service = service.MultiService() | ||||
engine_service.setServiceParent(main_service) | ||||
tub_service = Tub() | ||||
tub_service.setServiceParent(main_service) | ||||
# This needs to be called before the connection is initiated | ||||
main_service.startService() | ||||
# This initiates the connection to the controller and calls | ||||
# register_engine to tell the controller we are ready to do work | ||||
engine_connector = EngineConnector(tub_service) | ||||
furl_file = kernel_config['engine']['furl_file'] | ||||
Brian Granger
|
r1609 | log.msg("Using furl file: %s" % furl_file) | ||
Brian E Granger
|
r1234 | |||
Brian Granger
|
r1944 | def call_connect(engine_service, furl_file): | ||
d = engine_connector.connect_to_controller(engine_service, furl_file) | ||||
def handle_error(f): | ||||
# If this print statement is replaced by a log.err(f) I get | ||||
# an unhandled error, which makes no sense. I shouldn't have | ||||
# to use a print statement here. My only thought is that | ||||
# at the beginning of the process the logging is still starting up | ||||
print "error connecting to controller:", f.getErrorMessage() | ||||
reactor.callLater(0.1, reactor.stop) | ||||
d.addErrback(handle_error) | ||||
reactor.callWhenRunning(call_connect, engine_service, furl_file) | ||||
Brian E Granger
|
r1234 | reactor.run() | ||
def init_config(): | ||||
""" | ||||
Initialize the configuration using default and command line options. | ||||
""" | ||||
Brian Granger
|
r1959 | parser = OptionParser("""ipengine [options] | ||
Start an IPython engine. | ||||
Use the IPYTHONDIR environment variable to change your IPython directory | ||||
from the default of .ipython or _ipython. The log and security | ||||
subdirectories of your IPython directory will be used by this script | ||||
for log files and security files.""") | ||||
Brian E Granger
|
r1234 | |||
parser.add_option( | ||||
"--furl-file", | ||||
type="string", | ||||
dest="furl_file", | ||||
help="The filename containing the FURL of the controller" | ||||
) | ||||
parser.add_option( | ||||
"--mpi", | ||||
type="string", | ||||
dest="mpi", | ||||
help="How to enable MPI (mpi4py, pytrilinos, or empty string to disable)" | ||||
) | ||||
parser.add_option( | ||||
"-l", | ||||
"--logfile", | ||||
type="string", | ||||
dest="logfile", | ||||
help="log file name (default is stdout)" | ||||
) | ||||
(options, args) = parser.parse_args() | ||||
kernel_config = kernel_config_manager.get_config_obj() | ||||
# Now override with command line options | ||||
if options.furl_file is not None: | ||||
kernel_config['engine']['furl_file'] = options.furl_file | ||||
if options.logfile is not None: | ||||
kernel_config['engine']['logfile'] = options.logfile | ||||
if options.mpi is not None: | ||||
kernel_config['mpi']['default'] = options.mpi | ||||
def main(): | ||||
""" | ||||
After creating the configuration information, start the engine. | ||||
""" | ||||
init_config() | ||||
start_engine() | ||||
if __name__ == "__main__": | ||||
Vishal Vatsa
|
r1776 | main() | ||