Convert WindowsPath to String
Asked Answered
S

2

28
redpath = os.path.realpath('.')              
thispath = os.path.realpath(redpath)        
fspec = glob.glob(redpath+'/*fits')
thispath = os.path.realpath(thispath+'/../../../..')
p = Path(thispath)
userinput = 'n'
while (userinput == 'n'):
   text_file = next(p.glob('**/*.fits'))
   print("Is this the correct file path?")
   print(text_file)
   userinput = input("y or n")

parent_dir = text_file.parent.resolve()
fspec = glob.glob(parent_dir+'/*fits')

I am getting the error

unsupported operand type(s) for +: 'WindowsPath' and 'str'

I think this is because I am trying to glob a Windows File Path when I need to glob a string. Is there a way that I can convert WindowsPath to string so that I can glob all the files into one list?

Sinuate answered 15/10, 2018 at 21:41 Comment(5)
Instead of + try os.path.join(). https://mcmap.net/q/49720/-how-should-i-write-a-windows-path-in-a-python-string-literalNeary
Which line of code? You have more info than we do.Snub
try type(parent_dir), I think it is WindowsPath (not str). + operation failing due to different types.Foliolate
Two things to consider: pathlib supports glob: clickme and also relative paths, which can be resolved like Path(...).resolve()Catholicon
Does this answer your question? How can I convert a pathlib Path object to a string?Corsica
F
51

As most other Python classes do, the WindowsPath class, from pathlib, implements a non-defaulted "dunder string" method (__str__). It turns out that the string representation returned by that method for that class is exactly the string representing the filesystem path you are looking for. Here an example:

from pathlib import Path

p = Path('E:\\x\\y\\z')
>>> WindowsPath('E:/x/y/z')

p.__str__()
>>> 'E:\\x\\y\\z'

str(p)
>>> 'E:\\x\\y\\z'

The str builtin function actually calls the "dunder string" method under the hood, so the results are exaclty the same. By the way, as you can easily guess calling directly the "dunder string" method avoids a level of indirection by resulting in faster execution time.

Here the results of the tests I've done on my laptop:

from timeit import timeit

timeit(lambda:str(p),number=10000000)
>>> 2.3293891000000713

timeit(lambda:p.__str__(),number=10000000)
>>> 1.3876856000000544

Even if calling the __str__ method may appear a bit uglier in the source code, as you saw above, it leads to faster runtimes.

Fredericafrederich answered 16/6, 2019 at 19:9 Comment(2)
The str(variable) solved a similar problem for me whilst piping from pathLib.Path(variable) with a string variable Frankensteinian stitching operating. Thanks!Wabash
Note that you shouldn't call special methods directly. You should always use str() / len() / ... because they check the return type (in this case it doesn't matter)Sofiasofie
M
4

You are right, you need a string when you call glob.glob. In the last line of your code, parent_dir is a pathlib.Path object, which you cannot concatenate with the string '/*fits'. You need to explicitly convert parent_dir to a string by passing it to the built-in str function.

The last line of your code should thus read:

fspec = glob.glob(str(parent_dir)+'/*fits')

To illustrate further, consider this example:

>>> from pathlib import Path
>>> path = Path('C:\\')
>>> path
WindowsPath('C:/')
>>> str(path)
'C:\\'
>>>
Modulus answered 16/6, 2019 at 19:38 Comment(1)
Pathlib supports glob: docs.python.org/3/library/pathlib.html#pathlib.Path.globCatholicon

© 2022 - 2024 — McMap. All rights reserved.