74

I'm trying to execute ansible2 commands...

When I do:

ansible-playbook -vvv -i my/inventory my/playbook.yml

I get:

Unexpected Exception: name 'basestring' is not defined the full traceback was:

Traceback (most recent call last):
  File "/usr/local/bin/ansible-playbook", line 85, in <module>
    sys.exit(cli.run())
  File "/usr/local/lib/python3.4/site-packages/ansible/cli/playbook.py", line 150, in run
    results = pbex.run()
  File "/usr/local/lib/python3.4/site-packages/ansible/executor/playbook_executor.py", line 87, in run
    self._tqm.load_callbacks()
  File "/usr/local/lib/python3.4/site-packages/ansible/executor/task_queue_manager.py", line 149, in load_callbacks
    elif isinstance(self._stdout_callback, basestring):
NameError: name 'basestring' is not defined

Here is ansible --version:

ansible 2.0.0.2
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

And here is python --version

Python 3.4.3
code_monk
  • 9,451
  • 2
  • 42
  • 41

7 Answers7

127

Ansible below version 2.5 requires Python 2.6 or 2.7 on the control host: Control Node Requirements

basestring is no longer available in Python 3. From What’s New In Python 3.0:

The builtin basestring abstract type was removed. Use str instead. The str and bytes types don’t have functionality enough in common to warrant a shared base class. The 2to3 tool (see below) replaces every occurrence of basestring with str.

So the solution is to either upgrade Ansible or downgrade Python.

udondan
  • 57,263
  • 20
  • 190
  • 175
  • 8
    in case this helps anyone else, when i installed ansible using `pip` and `pip3`, it erroneously pointed to python3, but when i did `pip2 install ansible`, it worked fine, putting this at the top of each ansible utility: `#!/usr/local/opt/python/bin/python2.7` – code_monk Jan 15 '16 at 03:26
  • 7
    I feel like this is a flaw in pip or python packages or something. I shouldn't be able to pip3 install something that isn't compatible with python3. – vastlysuperiorman Apr 07 '16 at 17:37
  • I was able to get this working by installing ansible@2.5.0: `python3 -m pip install ansible==2.5.0`. – absynce Aug 01 '19 at 14:28
  • 1
    following the [documentation](https://docs.python.org/2/library/functions.html#basestring), why not use `(str, bytes)` as `basestring`? For `isinstance(var, (str,bytes))` works perfectly. – Serk Oct 13 '20 at 11:47
  • So your suggestion is to rewrite the ansible code? Sure, go ahead... – udondan Oct 13 '20 at 11:53
25

basestring is not available in Python 3.:

This can be fixed for python 2.x and 3.x with the following:

try:
  basestring
except NameError:
  basestring = str
Chris Laidler
  • 358
  • 4
  • 4
  • 1
    Not that `isinstance(b"", basestring) == True` on Python 2 but `isinstance(b"", str) == False` on Python 3. – ostrokach Aug 01 '19 at 18:49
  • I like more this one since i need the code to run in both environments. I find it hacky but is the fit for me now. Thanks! – davidmpaz May 30 '20 at 06:55
1

I ran into this issue using Python 3 with Ansible and solved by forking the dopy project and installing dopy in my ansible script with:

name: git+https://github.com/eodgooch/dopy@0.4.0#egg=dopy.

If you are still getting errors be sure to change the version to 0.4.0 and remove any lingering dopy packages from your Python site-packages directory.

Also you could pip3 install git+https://github.com/eodgooch/dopy@0.4.0#egg=dopy instead of in your Ansible Task.

eodgooch
  • 1,322
  • 1
  • 11
  • 17
  • 1
    `pip uninstall dopy` and `pip3 install git+https://github.com/eodgooch/dopy@0.4.0#egg=dopy` worked for me. Thank you! – wesgarrison Jul 02 '19 at 01:49
1

Replace basestring with str. In 2.x basestring is there. but in 3.x the basestring has been replaced with "str".

Dila Gurung
  • 1,726
  • 21
  • 26
0

The problem might be due to python version. In 2.x, basestring is there but in 3.x it has been replaced with "str".

Dila Gurung
  • 1,726
  • 21
  • 26
0

Another possible solution is to install future via pip install future and import from past.builtins import basestring.

from past.builtins import basestring

Personally, I'm not crazy about this solution because:

  1. It requires installing another dependency.
  2. There are likely other backward compatibility issues mixing Python 3 and 2 code.
  3. It will only work in your code - you don't want to modify Ansible source code.

I offer it only because it's something I've used in the past to make my own code work in both Python 2 and 3.

cycgrog
  • 21
  • 3
0

replace basestring with (str, bytes) and it should work perfectly

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 15 '23 at 08:46