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,
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
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)
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)
- Use joinpath() function of the pathlib library.
- and then use str() function as:-
str(BASE_DIR.joinpath('db.sqlite3'))
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,
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)
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)
- Use joinpath() function of the pathlib library.
- and then use str() function as:-
str(BASE_DIR.joinpath('db.sqlite3'))