Using bioformats with python and virtualenvs



Python-bioformats is a python wrapper for bioformats. Useage is explained in the docs and seems relatively straightforward.

import javabridge
import bioformats

Note that you also typically have to tell javabridge where the bioformats jars are like so:

other_jars = javabridge.JARS+bioformats.JARS+['/Users/Nick/bin/bioformats_package.jar']

This adds the default jars, the bioformats jars and my copy of the bioformats package to the search path.
The issue I had was when I try to import javabridge I get the following error:

Failed to run /usr/libexec/java_home, defaulting to best guess for Java
Traceback (most recent call last):
  File "/Users/Nick/.virtualenvs/cars/lib/python3.6/site-packages/javabridge/", line 45, in find_javahome
    os.path.join(os.path.dirname(path), "Libraries"),
  File "/Users/Nick/.virtualenvs/cars/bin/../lib/python3.6/", line 92, in join
    genericpath._check_arg_types('join', a, *p)
  File "/Users/Nick/.virtualenvs/cars/bin/../lib/python3.6/", line 151, in _check_arg_types
    raise TypeError("Can't mix strings and bytes in path components") from None
TypeError: Can't mix strings and bytes in path components

Weird. And no clear explanation on the internet. I did find one post explaining that OSX default java path is /usr/libexec/java_home, which is not necessarily where java is installed.
When I checked my path on Bash:

which java

I got my typical bin. This post explained that you need to set the JAVA_HOME variable. A quick inspection of the javabridge/ (as indicated in the error) shows the following check:

# javabridge/
def find_javahome():
     """Find JAVA_HOME if it doesn't exist"""
     if 'JAVA_HOME' in os.environ:
         return os.environ['JAVA_HOME']
     elif is_mac:
         # Use the "java_home" executable to find the location

Simple enough, just set the environmental variable in ~/.bash_profile

echo JAVA_HOME=/usr/bin/java >> ~/.bash_profile

now when I echo JAVA_HOME


Great. Unfortunately, when I started up an ipython shell in my virtualenvironment and check my environmental variables (print(os.environ)), JAVA_HOME is nowhere to be found.


When working in a virtualenv, not all of your system path variables are translated over.
A fix for this is explained in the virtualenvwrapper docs, you simply add a Hook script.
In my case I added the following line to my postactivate script:

export JAVA_HOME

Now whenever I activate my virtualenv and check my path with os.environ, I see my variable exists. Now I can use python-bioformats.