124

I'm doing something like this:

import pathlib

p = pathlib.Path("temp/").mkdir(parents=True, exist_ok=True)

with p.open("temp."+fn, "w", encoding ="utf-8") as f:
    f.write(result)

Error message: AttributeError: 'NoneType' object has no attribute 'open'

Obviously, based on the error message, mkdir returns None.

Jean-Francois Fabre suggested this correction:

p = pathlib.Path("temp/")
p.mkdir(parents=True, exist_ok=True)

with p.open("temp."+fn, "w", encoding ="utf-8") as f:
    ...

This triggered a new error message:

File "/Users/user/anaconda/lib/python3.6/pathlib.py", line 1164, in open opener=self._opener)
TypeError: an integer is required (got type str)

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Bondrak
  • 1,370
  • 2
  • 9
  • 15

6 Answers6

141

You could try:

p = pathlib.Path("temp/")
p.mkdir(parents=True, exist_ok=True)
fn = "test.txt" # I don't know what is your fn
filepath = p / fn
with filepath.open("w", encoding ="utf-8") as f:
    f.write(result)

You shouldn't give a string as path. It is your object filepath which has the method open.

source

Till
  • 4,183
  • 3
  • 16
  • 18
46

You can directly initialize filepath and create parent directories for parent attribute:

from pathlib import Path

filepath = Path("temp/test.txt")
filepath.parent.mkdir(parents=True, exist_ok=True)

with filepath.open("w", encoding ="utf-8") as f:
    f.write(result)
Anton Protopopov
  • 30,354
  • 12
  • 88
  • 93
21

Maybe, this is the shortest code you want to do.

import pathlib

p = pathlib.Path("temp/")
p.mkdir(parents=True, exist_ok=True)
(p / ("temp." + fn)).write_text(result, encoding="utf-8")

In most cases, it doesn't need even open() context by using write_text() instead.

Yukihiko Shinoda
  • 805
  • 2
  • 8
  • 21
15

The pathlib module offers an open method that has a slightly different signature to the built-in open function.

pathlib:

Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)

The built-in:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

In the case of this p = pathlib.Path("temp/") it has created a path p so calling p.open("temp."+fn, "w", encoding ="utf-8") with positional arguments (not using keywords) expects the first to be mode, then buffering, and buffering expects an integer, and that is the essence of the error; an integer is expected but it received the string 'w'.

This call p.open("temp."+fn, "w", encoding ="utf-8") is trying to open the path p (which is a directory) and also providing a filename which isn't supported. You have to construct the full path, and then either call the path's open method or pass the full path into the open built-in function.

Davos
  • 5,066
  • 42
  • 66
  • 1
    isn't this simpler: `p = pathlib.Path("temp/"); p.mkdir(parents=True, exist_ok=True)`? – Charlie Parker Jan 21 '21 at 16:57
  • 2
    @CharlieParker The OP's question can be summarised as "I tried this and had an error ... I tried that and had another error" Read the code examples in the question carefully and you see that the errors relate to (very common) confusion between the `method` signature and the built-in `function` signature. It's useful to imagine trying to explain the issue to yourself, back when you were first learning, in a way that you wish someone would have helped you then. – Davos Jan 22 '21 at 14:39
  • @CharlieParker (3 years ago now) I didn't suggest code or any opinion about what might be simpler, so I am not sure what you are asking, Also not sure why I got a downvote without a reason or feedback. – Davos Jan 27 '21 at 13:31
8

You can also do something like:

text_path = Path("random/results").resolve()
text_path.mkdir(parents=True, exist_ok=True)
(text_path / f"{title}.txt").write_text(raw_text)
anapaulagomes
  • 335
  • 4
  • 11
0

You are almost there. The full pathlib version would be something like:

folder = "path/to/folder"
file_base = "file_name_base"
file_extension = ".extension"

p_folder = pathlib.Path(folder)
p_file_base = p_folder / file_base
p_file = p_file_base.with_suffix(file_extension)

p_file.parent.mkdir(parents=True, exist_ok=True)  # or `p_folder`

p_file.write_text("Your text here", encoding ="utf-8")

I decomposed all steps to make it as transparent as possible, you can shorten this code. For example:

p_file = pathlib.Path("path/to/folder/file_base")
p_file.parent.mkdir(parents=True, exist_ok=True)
p_file.with_suffix(".extension").write_text("Your text here", encoding ="utf-8")
Sylvain
  • 679
  • 9
  • 13