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

Question:

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,

Asked By: CWeasel

||

Answers:

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

Answered By: PirateNinjas

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)
Answered By: cyberGhoul

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)
Answered By: Joost Döbken
  1. Use joinpath() function of the pathlib library.
  2. and then use str() function as:-
    str(BASE_DIR.joinpath('db.sqlite3'))
Answered By: Neel Mani
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.