Jython V2.7 behavior changes
Discover what we need to know when porting Jython V2.1 scripts to use Jython V2.7.
The following are known Jython behavioral changes in V2.7. If our script does not work properly with Jython V2.7, update our script using the following suggestions or stay with the older Jython V2.1:
- Deprecated library modules in Jython V2.7
- String behavior changes
- Changes to sys.exit() function
- Changes to importing modules
- How to raise a string exception
- Numeric type changes
Deprecated library modules in Jython V2.7
Some V2.1 library modules were deprecated or rewritten for Jython V2.7. So if your Jython V2.7 script imports them, we receive an ImportError like so:
WASX7017E: Exception received while running file "c:/test.py"; exception information: com.ibm.bsf.BSFException: exception from Jython: Traceback (most recent call last): File "<string>", line 1, in <module> ImportError: No module named jreloadWe need to rewrite your Jython script to use the most recent Jython library functions available in V2.7 or continue to use the older Jython V2.1 if we do not want to update our script.Deprecated Jython library modules:
- dospath
- gopherlib
- javaos
- jreload
- reconvert
- tzparse
- whrandom
The javaos module was replaced with os. Most of the jreload functions are contained within ihooks in V2.7.
String behavior changes
The String handling behavior uses a default string type of Unicode in V2.7. It does not impact the existing WAS functions, but it displays the returned string as Jython Unicode string with a string literal u prepended for example, u'string. The user can specify print command to display the regular string or call str() command to convert Jython Unicode string to a regular string such as:
AdminConfig.list('Node') u'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)' # use print command to display regular string print AdminConfig.list('Node') TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1) TestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1) nodes = AdminConfig.list('Node') u'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)' print nodes TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1) TestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1) # Call str() command to convert unicode string to regular string nodes = str(nodes) nodes 'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)'
Changes to sys.exit() function
The sys.exit() raises a SystemExit exception, so it expects to capture the SystemExit exception. It does not need to raise the SystemExit exception in v2.1, but your script can fail with the SystemExit error if we do not capture the SystemExit exception in v2.7:
See example code test.py, which demonstrates this behavior:
test.py: a = 5 b = 6 if (a > b): print "a > b" sys.exit(1) else: print " a < b" sys.exit(0)The following exception occurs:
WASX7017E: Exception received while running file "c:/q.py"; exception information: com.ibm.bsf.BSFException: exception from Jython: Traceback (most recent call last): File "<string>", line 12, in <module> SystemExit: 0The problem can be avoided using any one of the following solutions:
- Comment out sys.exit() if we don't want to raise the SystemExit exception.
- Use os._exit() function instead of sys.exit() if we don't want to trigger an exception.
test.py: import os a = 5 b = 6 if (a > b): print "a > b" os._exit(1) else: print "a < b" os._exit(0)- Capture the SystemExit exception to detect the SystemExit error and raise an exception.
test.py: a = 5 b = 6 try: if (a > b): print "a > b" sys.exit(1) else: print "a < b" sys.exit(0) except SystemExit: print "sys.exit() worked as expected" except: print "Something went wrong"
Changes to importing modules
If our Jython script needs to import a module, the module can be placed in the wsadmin working directory or it can be placed in another location.
For example:
test.py contains the following line:
import customThe custom.py can be placed in the wsadmin working directory such as c:\WebSphere\AppServer\profiles\dmgr01\bin where wsadmin is run.
The custom.py is automatically loaded when we run test.py such as:
wsadmin -f c:/test.pyIf custom.py is placed in other location such as c:\customscripts directory, we need to specify -profile <profile_module> to import the custom module such as:
wsadmin -profile c:/customscripts/custom.py -f c:/test.pyIf we need to import multiple modules located in different locations, for example:
- test1.py is in the profile_root/profile directory
- test2.py is in the profile_root/ directory
We can add modules through multiple -profile <profile_module> commands such as:
wsadmin -profile <profile_root/profile/test1.py> -profile <profile_root/test2.py> -f c:/test.pyOr we can add the modules path through the Jython system property python.path and it appends the paths to the property python.path when Jython is loaded such as:
wsadmin.sh -lang jython -javaoption "-Dpython.path=<profile_root/profile>;< profile_root>" -f c:/test.pyIf our importing module invokes wsadmin Admin commands, we can receive the NameError: global name 'AdminConfig' is not defined error message. It can complain about other Admin objects such as AdminControl, AdminApp, AdminTask, or Help as well. With Jython 2.7, Admin objects no longer register in the global name space so we need to retrieve it from system local name space instead.
For example, if custom.py contains the function print1(), which invokes the wsadmin AdminConfig.list() command:
def print1(): print "I am custom" nodes = AdminConfig.list('Node') print "Nodes: " + nodesWhen we run test.py, we can receive the error:
WASX7017E: Exception received while running file "c:/test.py"; exception information: com.ibm.bsf.BSFException: exception from Jython: Traceback (most recent call last): File "<string>", line 15, in <module> File "<string>", line 9, in print2 File "c:\custom.py", line 21, in print1 cell = AdminConfig.list('Cell') NameError: global name 'AdminConfig' is not definedTo resolve the NameError, add the following Jython commands in front of our importing module script (not the calling script):
#custom.py: import sys # Retrieve scripting objects from system local name space AdminConfig = sys._getframe(1).f_locals['AdminConfig']We can retrieve other Admin objects too if your script invokes other Admin commands:
AdminApp = sys._getframe(1).f_locals['AdminApp'] AdminControl = sys._getframe(1).f_locals['AdminControl'] AdminTask = sys._getframe(1).f_locals['AdminTask'] Help = sys._getframe(1).f_locals['Help'] def print1(): print "I am custom" nodes = AdminConfig.list('Node') print "Nodes: " + nodes
How to raise a string exception
Jython V2.7 does not allow raising a string exception, so we need to either raise an exception or error such as ValueError, AttributeError, TypeError, or create our own error type in a Jython class.
For example:
test.py: nodeName = "testNode1" if (nodeName != "testNode2"): raise "Could not find node name '%s'" % (nodeName)It works with Jython 2.1, but we receive the following TypeError in Jython V2.7:
WASX7017E: Exception received while running file "c:/p.py"; exception information: com.ibm.bsf.BSFException: exception from Jython: Traceback (most recent call last): File "<string>", line 5, in <module> TypeError: exceptions must be old-style classes or derived from BaseException, not strWe need to rewrite your script to raise as an exception or a ValueError/TypeError/AttributeError.
- Raise an exception:
if (nodeName != "testNode2"): raise Exception("Could not find node name '%s'" % (nodeName))- Raise a ValueError:
if (nodeName != "testNode2"): raise ValueError("Could not find node name '%s'" % (nodeName))- Create our own error type in a Jython class:
class MyError(Exception): '''raise this when there's an error from my command''' if nodeName != "testNode2": raise MyError("Could not find node name '%s'" % (nodeName))
Numeric type changes
In Jython V2.1, numeric types were Py objects like PyInteger or PyFloat and as such had methods like toString(). In Jython V2.7, numeric types are more like native types and do not have these basic Object methods available. The difference was discovered when an integer is passed into a Jython function and its value is printed using the toString() method.
In Jython V2.7, using this sample code:
foo = 3.1415 print "foo =", foo.toString() foo =Results in the following error:
WASX7015E: Exception running command: ""foo =", foo.toString()"; exception information: com.ibm.bsf.BSFException: exception from Jython: Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'float' object has no attribute 'toString'To display the numeric type:
print "foo = %f" % foo foo = 3.141500
Related:
Use wsadmin scripting with Jacl (deprecated) Use wsadmin scripting with Jython Get started with wsadmin scripting IBM Jacl to Jython Conversion Assistant WAS Administration Using Jython