WebSphere Jython scripting, sys.argv[0] and __file__

Today’s problem is that wsadmin sets up sys.argv differently from normal Python (or Jython).  In Python, sys.argv[0] is the name of the script you invoked.  What you’d normally think of as the command line arguments start at index 1.  For whatever reason, wsadmin doesn’t pass the script name.  The arguments are passed in starting at sys.argv[0].  This can be a nuisance if you have a script that you want to run both in wsadmin and Python.  It’s also just one more difference to trip over.

I should give credit to this post for reminding me that this needs fixing and also for pointing out that the full command line is available in the environment.  Thanks!

My code for this is a little clumsy.  Basically, we scan the command line we get from IBM_JAVA_COMMAND_LINE for the -f option.  We  don’t want to pick up just any -f that might be passed as an argument to the script, easy to avoid by stripping off anything after a -- argument.  We also don’t want to pick up a -f that might appear among all the environment data that wsadmin prepends to the command line (unlikely as that might be), so we look for the last -f after removing any -- that might be present.  Even so, if the script name contains a space, we’re not going to get the whole name.  Such is life.

topframe = sys._getframe()
up1frame = topframe.f_back
while topframe.f_back:
    topframe = topframe.f_back

cmdline = os.environ.get('IBM_JAVA_COMMAND_LINE')
if up1frame == topframe and cmdline and not topframe.f_globals.get('__file__'):
    beg = 0
    end = len(cmdline)
    # Throw away everything after the '--', if present.
    dashdash = cmdline.find('--', beg, end)
    if dashdash >= 0:
        end = dashdash
    # If we can't find a filename, just use a "-"
    mainfile = '-'
    dashf = cmdline.rfind(' -f ', beg, end)
    if dashf:
        # Grab everything from after the "-f" to the following space.
        beg = dashf + 4
        space = cmdline.find(' ', beg, end)
        if space >= 0:
            end = space
        mainfile = cmdline[beg:end]
    sys.argv[:0] = [ mainfile ]
    topframe.f_globals['__file__'] = mainfile

By the way, I threw in a little bonus.  In wsadmin, __file__ isn’t normally set for the top-level script.  That last line will set it.

As usual, the complete listing for this evolving bundle of fixes is ibmfixes.py.

Update 4/16/2010: I decided this fix should only be applied if imported directly from the top level. This will keep it from potentially breaking existing main programs that don’t know about it.