When I develop with Python, I like to use its interactive interpreter to experiment with code samples quickly and in real time. It allows me to import the code I've been developing so I can test it in a controlled environment. Java doesn't include this ability outnatively, but there are a number of ways to accomplish something similar with additional software. With my preference for Python, I chose Jython to do this.
- Install Jython. See jython.org for details. It may be as simple as, for example, on OS X with Homebrew:
brew install jython
- Use Maven to set the Java classpath for Jython from the project dependencies. This allows Jython to import all of the classes the project's Java code uses. This could be set in the
CLASSPATH
environment variable, but that would affect other Java programs. To limit this classpath to Jython, set theJYTHONPATH
environment variable instead:
JYTHONPATH=$(mvn -q dependency:build-classpath -Dmdep.outputFile=/dev/stdout); export JYTHONPATH
If the project dependencies change, this step needs to be run again. The Maven dependency plugin has features that may be used to automate this somewhat.
- View the value of
JYTHONPATH
to verify it is set correctly.
echo $JYTHONPATH
/Users/lsloan/.m2/repository/joda-time/joda-time/2.4/joda-time-2.4.jar:/Users/lsloan/.m2/repository/org/imsglobal/caliper/caliper-java/1.0.0/caliper-java-1.0.0.jar
- Start the Jython interactive interpreter and verify the path includes the classpath set in the previous step.
jython
Jython 2.7.0 (default:9987c746f838, Apr 29 2015, 02:25:11)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.8.0_65
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/Users/lsloan/.m2/repository/joda-time/joda-time/2.4/joda-time-2.4.jar', '/Users/lsloan/.m2/repository/org/imsglobal/caliper/caliper-java/1.0.0/caliper-java-1.0.0.jar', '/Local/Cellar/jython/2.7.0/libexec/Lib', '__classpath__', '__pyclasspath__/', '/Local/Cellar/jython/2.7.0/libexec/Lib/site-packages']
- Import a Java class found only in the classpath and try using it. Remember to use Java objects in a Pythonic way.
>>> from org.joda.time import DateTime
>>> dt = DateTime()
>>> dt
2016-06-29T16:40:18.006-04:00
Try using Jython's autocompletion and history features to make typing or reusing Python statements easier. At the interpreter prompt, type dt.get
, then press the Tab key. Jython will display the possible completions:
dt.get( dt.getCenturyOfEra( dt.getChronology(
dt.getClass( dt.getDayOfMonth( dt.getDayOfWeek(
dt.getDayOfYear( dt.getEra( dt.getHourOfDay(
dt.getMillis( dt.getMillisOfDay( dt.getMillisOfSecond(
dt.getMinuteOfDay( dt.getMinuteOfHour( dt.getMonthOfYear(
dt.getSecondOfDay( dt.getSecondOfMinute( dt.getWeekOfWeekyear(
dt.getWeekyear( dt.getYear( dt.getYearOfCentury(
dt.getYearOfEra( dt.getZone(
Try using other methods of the DateTime object:
>>> dt.getMonthOfYear()
6
>>> dt.plusHours(2)
2016-06-29T18:40:18.006-04:00
Use the Python dir()
function to get a list of valid attributes for the object. Notice the Pythonic symbols are shown along with the Java properties and methods.
>>> dir(dt)
['Property', '__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__', '__ensure_finalizer__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasshook__', '__unicode__', 'afterNow', 'beforeNow', 'centuryOfEra', 'chronology', 'class', 'compareTo', 'dayOfMonth', 'dayOfWeek', 'dayOfYear', 'equalNow', 'equals', 'era', 'get', 'getCenturyOfEra', 'getChronology', 'getClass', 'getDayOfMonth', 'getDayOfWeek', 'getDayOfYear', 'getEra', 'getHourOfDay', 'getMillis', 'getMillisOfDay', 'getMillisOfSecond', 'getMinuteOfDay', 'getMinuteOfHour', 'getMonthOfYear', 'getSecondOfDay', 'getSecondOfMinute', 'getWeekOfWeekyear', 'getWeekyear', 'getYear', 'getYearOfCentury', 'getYearOfEra', 'getZone', 'hashCode', 'hourOfDay', 'isAfter', 'isAfterNow', 'isBefore', 'isBeforeNow', 'isEqual', 'isEqualNow', 'isSupported', 'millis', 'millisOfDay', 'millisOfSecond', 'minus', 'minusDays', 'minusHours', 'minusMillis', 'minusMinutes', 'minusMonths', 'minusSeconds', 'minusWeeks', 'minusYears', 'minuteOfDay', 'minuteOfHour', 'monthOfYear', 'notify', 'notifyAll', 'now', 'parse', 'plus', 'plusDays', 'plusHours', 'plusMillis', 'plusMinutes', 'plusMonths', 'plusSeconds', 'plusWeeks', 'plusYears', 'property', 'secondOfDay', 'secondOfMinute', 'toCalendar', 'toDate', 'toDateMidnight', 'toDateTime', 'toDateTimeISO', 'toGregorianCalendar', 'toInstant', 'toLocalDate', 'toLocalDateTime', 'toLocalTime', 'toMutableDateTime', 'toMutableDateTimeISO', 'toString', 'toTimeOfDay', 'toYearMonthDay', 'wait', 'weekOfWeekyear', 'weekyear', 'withCenturyOfEra', 'withChronology', 'withDate', 'withDayOfMonth', 'withDayOfWeek', 'withDayOfYear', 'withDurationAdded', 'withEarlierOffsetAtOverlap', 'withEra', 'withField', 'withFieldAdded', 'withFields', 'withHourOfDay', 'withLaterOffsetAtOverlap', 'withMillis', 'withMillisOfDay', 'withMillisOfSecond', 'withMinuteOfHour', 'withMonthOfYear', 'withPeriodAdded', 'withSecondOfMinute', 'withTime', 'withTimeAtStartOfDay', 'withWeekOfWeekyear', 'withWeekyear', 'withYear', 'withYearOfCentury', 'withYearOfEra', 'withZone', 'withZoneRetainFields', 'year', 'yearOfCentury', 'yearOfEra', 'zone']
- Continue exploring!