# Buggy code
def _get_shebang(interpreter, task_vars, args=tuple()):
    """
    Note not stellar API:
       Returns None instead of always returning a shebang line.  Doing it this
       way allows the caller to decide to use the shebang it read from the
       file rather than trust that we reformatted what they already have
       correctly.
    """
    interpreter_config = "ansible_%s_interpreter" % os.path.basename(interpreter)

    if interpreter_config not in task_vars:
        return (None, interpreter)

    interpreter = task_vars[interpreter_config]
    shebang = "#!" + interpreter

    if args:
        shebang = shebang + " " + " ".join(args)

    return (shebang, interpreter)


# Traceback (OSError)
% ansible-playbook -vvvv -i inventory playbook.yml
Using /Users/jladd/.ansible.cfg as config file
Loaded callback default of type stdout, v2.0

PLAYBOOK: playbook.yml *********************************************************
1 plays in playbook.yml

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: jladd
<127.0.0.1> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270 `" &amp;&amp; echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270 `" )'
<127.0.0.1> PUT /var/folders/9f/lfcc9zd96fngv4bpptdg86700000gn/T/tmp7VbvKW TO /Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup
<127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/env python /Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup; rm -rf "/Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/" > /dev/null 2>&amp;1'
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
File "/Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup", line 114, in <module>
exitcode = invoke_module(module, zipped_mod, ZIPLOADER_PARAMS)
File "/Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup", line 28, in invoke_module
p = subprocess.Popen(['/usr/bin/env python', module], env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

fatal: [127.0.0.1]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "setup"}, "module_stderr": "Traceback (most recent call last):\n  File \"/Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup\", line 114, in <module>\n    exitcode = invoke_module(module, zipped_mod, ZIPLOADER_PARAMS)\n  File \"/Users/jladd/.ansible/tmp/ansible-tmp-1461804617.07-35816113603270/setup\", line 28, in invoke_module\n    p = subprocess.Popen(['/usr/bin/env python', module], env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)\n  File \"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py\", line 710, in __init__\n    errread, errwrite)\n  File \"/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py\", line 1335, in _execute_child\n    raise child_exception\nOSError: [Errno 2] No such file or directory\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}

NO MORE HOSTS LEFT *************************************************************
to retry, use: --limit @playbook.retry

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=0    changed=0    unreachable=0    failed=1

# Fixed code
def _get_shebang(interpreter, task_vars, args=tuple()):
    """
    Note not stellar API:
       Returns None instead of always returning a shebang line.  Doing it this
       way allows the caller to decide to use the shebang it read from the
       file rather than trust that we reformatted what they already have
       correctly.
    """
    interpreter_config = (
        "ansible_%s_interpreter" % os.path.basename(interpreter).strip()
    )

    if interpreter_config not in task_vars:
        return (None, interpreter)

    interpreter = task_vars[interpreter_config].strip()
    shebang = "#!" + interpreter

    if args:
        shebang = shebang + " " + " ".join(args)

    return (shebang, interpreter)