Python os.path.join() on a list
Asked Answered
A

5

146

I can do

>>> os.path.join("c:/","home","foo","bar","some.txt")
'c:/home\\foo\\bar\\some.txt'

But, when I do

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(s)
['c:/', 'home', 'foo', 'bar', 'some.txt']

What am I missing here?

Astounding answered 12/2, 2013 at 6:40 Comment(0)
A
259

The problem is, os.path.join doesn't take a list as argument, it has to be separate arguments.

To unpack the list into separate arguments required by join (and for the record: list was obtained from a string using split), use * - or the 'splat' operator, thus:

>>> s = "c:/,home,foo,bar,some.txt".split(",")
>>> os.path.join(*s)
'c:/home\\foo\\bar\\some.txt'
Astounding answered 12/2, 2013 at 6:40 Comment(2)
some more context for splat: docs.python.org/2/tutorial/…Rohrer
Note that I tried to use this to remove the last part of a full path. It resulted in an error (in Mac), as it was missing the first slash at /Users/.... To solve it, I added that leading slash manually, in case somebody faces the same problem...Hestia
C
32

Assuming join wasn't designed that way (which it is, as ATOzTOA pointed out), and it only took two parameters, you could still use the built-in reduce:

>>> reduce(os.path.join,["c:/","home","foo","bar","some.txt"])
'c:/home\\foo\\bar\\some.txt'

Same output like:

>>> os.path.join(*["c:/","home","foo","bar","some.txt"])
'c:/home\\foo\\bar\\some.txt' 

Just for completeness and educational reasons (and for other situations where * doesn't work).

Hint for Python 3

reduce was moved to the functools module.

Cento answered 12/2, 2013 at 10:39 Comment(3)
In Python 3 reduce was moved to functools module in case anyone else was looking for it as I was.Agleam
pity that python walks more and more away from functional style instead of embracing it and opening up. moving reduce away to a module is a statement.Silurian
Even in 2.7 one can from functools import reduceNipa
B
18

I stumbled over the situation where the list might be empty. In that case:

os.path.join('', *the_list_with_path_components)

Note the first argument, which will not alter the result.

Buttocks answered 17/4, 2014 at 16:43 Comment(1)
os.path.join('', *the_list_with_path_components) is not adding the leading slash in python 2.7, i am curious how can i preserve this slashKailyard
C
11

It's just the method. You're not missing anything. The official documentation shows that you can use list unpacking to supply several paths:

s = "c:/,home,foo,bar,some.txt".split(",")
os.path.join(*s)

Note the *s intead of just s in os.path.join(*s). Using the asterisk will trigger the unpacking of the list, which means that each list argument will be supplied to the function as a separate argument.

Checker answered 12/2, 2013 at 6:44 Comment(2)
Better look into your link once more ;-)Cento
@Checker it is prefered on SO to copy the relevant parts into the answer and not just paste a link, maybe therefore the downvotesSilurian
E
2

This can be also thought of as a simple map reduce operation if you would like to think of it from a functional programming perspective.

import os
folders = [("home",".vim"),("home","zathura")]
[reduce(lambda x,y: os.path.join(x,y), each, "") for each in folders]

reduce is builtin in Python 2.x. In Python 3.x it has been moved to itertools However the accepted the answer is better.

This has been answered below but answering if you have a list of items that needs to be joined.

Ease answered 6/7, 2015 at 10:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.