TypeError: join() argument must be str or bytes, not 'PosixPath'

Viewed 4906

So, I'm receiving the following error: TypeError: join() argument must be str or bytes, not 'PosixPath'

It happens while checking my Django installation on Ubuntu 16.04. The full error would be:

    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
  File "/usr/lib/python3.5/posixpath.py", line 89, in join
    genericpath._check_arg_types('join', a, *p)
  File "/usr/lib/python3.5/genericpath.py", line 143, in _check_arg_types
    (funcname, s.__class__.__name__)) from None
TypeError: join() argument must be str or bytes, not 'PosixPath'

This is from the settings.py file.

In the file I have:

from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

On my development environment it is working and running through it, yet here I receive the error. The version of Python on production is 3.5.1-3. Normally the packages should be installed the same as well (pip freeze/install -r).

Anyone have an idea to push me in the correct direction?

Thanks in advance,

3 Answers

using only the pathlib library makes it much easier:

BASEPATH = Path(__file__).resolve().parent.parent

STATIC_ROOT = BASEPATH.joinpath('static')
MEDIA_ROOT = BASEPATH.joinpath('media')

The PosixPath gives much more freedom to specify, for example, only file names, or a list of files. Ultimately, you can always convert the PosixPath to string:

str(MEDIA_ROOT)

So the issue here is that your BASE_DIR is a pathlib Path, while os.path.join usually works with strings. I would instead use purely pathlib, like so:

from pathlib import Path
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
...
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'

MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

This lets pathlib handle the path joins and happens to be a bit simpler and easier to read (opinion).

Edit: Just wanted to add, that as of python 3.6, os.path.join should handle all path-like object, which is why it may work in some environments - see the docs: https://docs.python.org/3/library/os.path.html#os.path.join

It is because Path(file).resolve().parent.parent returns an object. But for 'join' function a tring is needed so change:

BASE_DIR = Path(__file__).resolve().parent.parent

to:

BASE_DIR = str(Path(__file__).resolve().parent.parent)
Related