[python] Python os.path.join on Windows

I am trying to learn python and am making a program that will output a script. I want to use os.path.join, but am pretty confused. According to the docs if I say:

os.path.join('c:', 'sourcedir')

I get "C:sourcedir". According to the docs, this is normal, right?

But when I use the copytree command, Python will output it the desired way, for example:

import shutil
src = os.path.join('c:', 'src')
dst = os.path.join('c:', 'dst')
shutil.copytree(src, dst)

Here is the error code I get:

WindowsError: [Error 3] The system cannot find the path specified: 'C:src/*.*'

If I wrap the os.path.join with os.path.normpath I get the same error.

If this os.path.join can't be used this way, then I am confused as to its purpose.

According to the pages suggested by Stack Overflow, slashes should not be used in join—that is correct, I assume?

This question is related to python windows path-manipulation

The answer is


to join a windows path, try

mypath=os.path.join('c:\\', 'sourcedir')

basically, you will need to escape the slash


The reason os.path.join('C:', 'src') is not working as you expect is because of something in the documentation that you linked to:

Note that on Windows, since there is a current directory for each drive, os.path.join("c:", "foo") represents a path relative to the current directory on drive C: (c:foo), not c:\foo.

As ghostdog said, you probably want mypath=os.path.join('c:\\', 'sourcedir')


You have a few possible approaches to treat path on Windows, from the most hardcoded ones (as using raw string literals or escaping backslashes) to the least ones. Here follows a few examples that will work as expected. Use what better fits your needs.

In[1]: from os.path import join, isdir

In[2]: from os import sep

In[3]: isdir(join("c:", "\\", "Users"))
Out[3]: True

In[4]: isdir(join("c:", "/", "Users"))
Out[4]: True

In[5]: isdir(join("c:", sep, "Users"))
Out[5]: True

For a system-agnostic solution that works on both Windows and Linux, no matter what the input path, one could use os.path.join(os.sep, rootdir + os.sep, targetdir)

On WIndows:

>>> os.path.join(os.sep, "C:" + os.sep, "Windows")
'C:\\Windows'

On Linux:

>>> os.path.join(os.sep, "usr" + os.sep, "lib")
'/usr/lib'

I'd say this is a (windows)python bug.

Why bug?

I think this statement should be True

os.path.join(*os.path.dirname(os.path.abspath(__file__)).split(os.path.sep))==os.path.dirname(os.path.abspath(__file__))

But it is False on windows machines.


answering to your comment : "the others '//' 'c:', 'c:\\' did not work (C:\\ created two backslashes, C:\ didn't work at all)"

On windows using os.path.join('c:', 'sourcedir') will automatically add two backslashes \\ in front of sourcedir.

To resolve the path, as python works on windows also with forward slashes -> '/', simply add .replace('\\','/') with os.path.join as below:-

os.path.join('c:\\', 'sourcedir').replace('\\','/')

e.g: os.path.join('c:\\', 'temp').replace('\\','/')

output : 'C:/temp'


The proposed solutions are interesting and offer a good reference, however they are only partially satisfying. It is ok to manually add the separator when you have a single specific case or you know the format of the input string, but there can be cases where you want to do it programmatically on generic inputs.

With a bit of experimenting, I believe the criteria is that the path delimiter is not added if the first segment is a drive letter, meaning a single letter followed by a colon, no matter if it corresponds to a real unit.

For example:

import os
testval = ['c:','c:\\','d:','j:','jr:','data:']

for t in testval:
    print ('test value: ',t,', join to "folder"',os.path.join(t,'folder'))
test value:  c: , join to "folder" c:folder
test value:  c:\ , join to "folder" c:\folder
test value:  d: , join to "folder" d:folder
test value:  j: , join to "folder" j:folder
test value:  jr: , join to "folder" jr:\folder
test value:  data: , join to "folder" data:\folder

A convenient way to test for the criteria and apply a path correction can be to use os.path.splitdrive comparing the first returned element to the test value, like t+os.path.sep if os.path.splitdrive(t)[0]==t else t.

Test:

for t in testval:
    corrected = t+os.path.sep if os.path.splitdrive(t)[0]==t else t
    print ('original: %s\tcorrected: %s'%(t,corrected),' join corrected->',os.path.join(corrected,'folder'))
original: c:    corrected: c:\  join corrected-> c:\folder
original: c:\   corrected: c:\  join corrected-> c:\folder
original: d:    corrected: d:\  join corrected-> d:\folder
original: j:    corrected: j:\  join corrected-> j:\folder
original: jr:   corrected: jr:  join corrected-> jr:\folder
original: data: corrected: data:  join corrected-> data:\folder

it can be probably be improved to be more robust for trailing spaces, and I have tested it only on windows, but I hope it gives an idea. See also Os.path : can you explain this behavior? for interesting details on systems other then windows.


To be even more pedantic, the most python doc consistent answer would be:

mypath = os.path.join('c:', os.sep, 'sourcedir')

Since you also need os.sep for the posix root path:

mypath = os.path.join(os.sep, 'usr', 'lib')

Consent with @georg-

I would say then why we need lame os.path.join- better to use str.join or unicode.join e.g.

sys.path.append('{0}'.join(os.path.dirname(__file__).split(os.path.sep)[0:-1]).format(os.path.sep))

To be pedantic, it's probably not good to hardcode either / or \ as the path separator. Maybe this would be best?

mypath = os.path.join('c:%s' % os.sep, 'sourcedir')

or

mypath = os.path.join('c:' + os.sep, 'sourcedir')

Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to windows

"Permission Denied" trying to run Python on Windows 10 A fatal error occurred while creating a TLS client credential. The internal error state is 10013 How to install OpenJDK 11 on Windows? I can't install pyaudio on Windows? How to solve "error: Microsoft Visual C++ 14.0 is required."? git clone: Authentication failed for <URL> How to avoid the "Windows Defender SmartScreen prevented an unrecognized app from starting warning" XCOPY: Overwrite all without prompt in BATCH Laravel 5 show ErrorException file_put_contents failed to open stream: No such file or directory how to open Jupyter notebook in chrome on windows Tensorflow import error: No module named 'tensorflow'

Examples related to path-manipulation

Given a filesystem path, is there a shorter way to extract the filename without its extension? How to get only the last part of a path in Python? Python os.path.join on Windows