First, you need to consider what problems Portal was designed to solve. Is it, as Wikipedia suggest, to bring together information from diverse sources in a unified way? If so, what other ways do we now have to do this?
Well, first, how do you bring together information from diverse sources? The obvious answer is to call a variety of (web) services. This introduces issues of contracts and network latency, blah blah blah, but these are things poorly solved by portal, so it's your call. Suppose the services are RESTful? Does that make managing contracts easier? Possibly.
Then, how do you unify the information? One of the issues that Portal solved was how to bring these disparate items onto one page, and have them load independently. AJAX has grown up since then, and the same effect can potentially be handled using XMLHttpRequest calls to the various (RESTful?) services to get your data, and then using a shared set of style sheets.
Will this work? It can and does. Is it more manageable than JSR286 portal servers? Probably. Are there still a ton of issues to overcome? Definitely. But it's a viable alternative.
The recommendation in Python is to use exceptions to indicate failure. This is true even if you expect failure on a regular basis.
Look at it from the perspective of the caller of your code:
my_status = get_abe_status(my_url)
What if we return None? If the caller doesn't specifically handle the case that get_abe_status failed, it will simply try to continue on with my_stats being None. That may produce a difficult to diagnose bug later on. Even if you do check for None, this code has no clue why get_abe_status() failed.
But what if we raise an exception? If the caller doesn't specifically handle the case, the exception will propagate upward eventually hitting the default exception handler. That may not be the what you want, but its better then introducing a subtle bug elsewhere in the program. Additionally, the exception gives information about what went wrong which is lost in the first version.
From the caller's perspective, its simply more convenient to get an exception than a return value. And that's the python style, to use exceptions to indicate failure conditions not return values.
Some will take a different perspective and argue that you should only use exceptions for cases you never really expect to happen. They argue that normally running running could should not raise any exceptions. One reason that is given for this is that exceptions are grossly inefficient, but that's not actually true for Python.
A couple of points on your code:
try:
hits[0]
except IndexError:
raise NotFoundError("No mentions found.")
That's a really confusing way to check for an empty list. Don't induce an exception just to check something. Use an if.
# say we expect four hits...
if len(hits) != 4:
raise Warning("An unexpected number of hits.")
logger.warning("An unexpected number of hits.")
You do realize that the logger.warning line will never run right?
Best Answer
You have options...
Implement you own log4j/logback appender (WriteYourOwnAppender) that "does what you want"
Use an SMTPAppender that accumulates logging events in one or more fixed-size buffers and sends the contents of the appropriate buffer in an email after a user-specified event occurs
Use a DBAppender that inserts logging events into three database tables in a format independent of the Java programming language
Use a SocketAppender that is designed to log to a remote entity by transmitting serialized ILoggingEvent instances over the wire. You would have to take care of the receiving side of course.
Use a SyslogAppender a that sends a small message to a syslog receiver. The receiver is commonly called
syslog daemon
orsyslog server
. Logback can send messages to a remote syslog daemon. In short, it will send all your exceptions (errors, warnings, depending how you configure it inlogback.properties
/xml
) to an OS syslog.Or, there is Bug4J, that you can either use via Bug4jAppender or through the Bug4J agent. Both will write into a Bug4J server which has a web gui that looks a bit nicer than ChainSaw (which, btw, is another way..):