Learn to write a native DNAnexus applet that executes a Python program
Use the dxpy module to download and upload files
Use the Python subprocess module to execute an external process and check the return value
Getting Started
We'll use the same scarlet.txt file from the bash version of the wc applet. Start off using dx-app-wizard and define the same inputs and outputs as before, but be sure to choose Python for the Programming language:
Template Options
You can write your app in any programming language, but we provide
templates for the following supported languages: Python, bash
Programming language: Python
Python Template
The Python template looks like the following:
python_wc.py
#!/usr/bin/env python# python_wc 0.1.0# Generated by dx-app-wizard.## Basic execution pattern: Your app will run on a single machine from# beginning to end.## See https://documentation.dnanexus.com/developer for documentation and# tutorials on how to modify this file.## DNAnexus Python Bindings (dxpy) documentation:# http://autodoc.dnanexus.com/bindings/python/current/import osimport dxpy@dxpy.entry_point('main')# 1defmain(input_file):# 2# The following line(s) initialize your data object inputs on the platform# into dxpy.DXDataObject instances that you can start using immediately. input_file = dxpy.DXFile(input_file)# 3# The following line(s) download your file inputs to the local file system# using variable names for the filenames. dxpy.download_dxfile(input_file.get_id(),"input_file")# 4# Fill in your application code here.# The following line(s) use the Python bindings to upload your file outputs# after you have created them on the local file system. It assumes that you# have used the output field name for the filename for each output, but you# can change that behavior to suit your needs. outfile = dxpy.upload_local_file("outfile")# 5# The following line fills in some basic dummy output and assumes# that you have created variables to represent your output with# the same name as your output fields. output ={} output["outfile"]= dxpy.dxlink(outfile)# 6return output # 7dxpy.run()
entry_point: DNAnexus execution environment entry point
The input_file listed in the inputSpec is passed to main.
Shadow the input_file variable, overwriting it with the creation of a new DXFile object.
Call dxpy.download_dxfile to download the input file identified by the file ID to the local_file name.
Execute wc on the local input file and redirect (>) the output to the chosen output filename. This function returns a tuple containing the process's return value and output (STDOUT/STDERR).
If the return value is not zero, use sys.exit to abort the program with the output from the system call.
If the program makes it to this point, the output file should have been created to upload.
Return a Python dictionary with the DNAnexus link to the new outfile object.
NOTE: Portable Operating System Interface (POSIX) standards dictate that processes return 0 on success (i.e., zero errors) and some positive integer value (usually in the range 1-127) to indicate an error condition.
Run dx build to build the applet. Create an job_input.json file with the file ID of your input:
Run your applet with the input file using --watch to see the output:
I can inspect the contents of the output file:
I can verify this is correct by piping the input file to a local execution of wc:
Debugging Locally
You can shorten the build/run development cycle by naming the JSON input job_input.json and executing the Python program locally:
This will download the input as input_file.txt and then create a new local file with the system call:
Review
You have now translated the bash applet for running wc into a native DNAnexus Python applet.
You were introduced to the dxpy module that provides functions for making API calls.
You used subprocess.getstatusoutput to call an external process and interpret the return value for success or failure.
In the next section, we'll continue translating bash to Python.