Diference between os.getcwd() and os.path.dirname(__file__) - python

In a previous project, I used the first version of the following two lines. Now that I found getcwd() I thought this would be the shorter alternative.
print(os.path.dirname(__file__)) # D:/Personal_Software/my_project
print(os.getcwd()) # D:\Personal_Software\my_project
I already read this post, but the thing I'm curious about is the use of "/" vs. "\". I'm using Windows 10 if that's relevant.

__file__ is filename provided to Python, exactly as it was provided.
os.path.dirname(__file__) is usually the directory in which a script is located. (But not always, as you'll see below.)
os.path.dirname(os.path.realpath(__file__)) is the directory in which the script is located.
os.getcwd() is the current directory.
The current directory has nothing to do with where the script is located. It's a per-process path used to resolve relative paths.
/tmp/ikegami/a.py:
#!/usr/bin/python3
import os
print(__file__)
print(os.path.dirname(__file__))
print(os.path.dirname(os.path.realpath(__file__)))
print(os.getcwd())
[~]$ bin/a # A symlink to /tmp/ikegami/a.py
bin/a # The path provided to python3.
bin # NOT the directory in which the script is located.
/tmp/ikegami # The directory in which the script is located.
/home/ikegami # The current directory (~ = /home/ikegami)
[~]$ /tmp/ikegami/a.py
/tmp/ikegami/a.py # The path provided to python3.
/tmp/ikegami # The parent of the path provided to python3.
/tmp/ikegami # The directory in which the script is located.
/home/ikegami # The current directory (~ = /home/ikegami)
[~]$ cd /tmp/ikegami
[/tmp/ikegami]$ ./a.py
./a.py # The path provided to python3.
. # The parent of the path provided to python3.
/tmp/ikegami # The directory in which the script is located.
/tmp/ikegami # The current directory
(Those test were run on a Linux machine because I don't have python installed on this Windows machine. You'll get similar results on Windows.)
the thing I'm curious about is the use of "/" vs. "\".
Windows has always accepted both \ and / as the directory separator.[1][2], and so did DOS before that.[3] These are equivalent. \ is the canonical separator (the one that's preferred for consistency), but / works just as well.
It appears that your program was launched using python3 D:/Personal_Software/my_project/file.py. __file__ contains the exact path provided to Python, and dirname(__file__) simply removes the last bit.
os.getcwd(), on the other hand, receives the current directory from the OS, and the OS probably returns the canonical form of the current directory.
You can even use // for UNC paths (//server/share) and similar (//?/..., //./..., etc).
Contrary to claims that have been made, this is the case for system calls (i.e. the Win32 API), this is the case in Explorer ("My Computer", "File Explorer", "Save As" dialogs, etc), this is the case for the Power Shell (e.g. dir "c:/bin", c:/bin/myprog), and this is case in the Windows console (e.g. c:/bin/myprog).
Caveat: Some specific Windows console commands (e.g. dir) requires paths with / to be in quotes (e.g. dir "c:/") because / signals the start of an option to them.
Well, since directories were introduced in DOS 2.0.

There is a difference, though you wouldn't be able to tell from a single script.
__file__ is the full filename of a loaded module or script, so getting the parent directory of it with os.path.dirname(__file__) gets you the directory that script is in.
Note: on Linux (and similar OSes), such a filename can be a symbolic link to the actual file which may reside somewhere else. You can use os.path.realpath() to resolve through any such links, if needed, although you can typically use the symlink equivalently. On Windows these are less common, but similarly, you can resolve symbolic links through realpath().
os.getcwd() gets you the current working directory. If you start a script from the directory the script is in (which is common), the working directory will be the same as the result from the call from os.path.dirname(__file__).
But if you start the script from another directory (i.e. python d:\some\path\script.py), or if you change the working directory during the script (e.g. with os.chdir()), the current working directory has changed, but the directory part of the script filename has not.
So, it depends on what you need:
Need the directory your script file is in? Use os.path.dirname(__file__)
Need the directory your script is currently running in? use os.getcwd()
You'll see / in some results and \ in others. Sadly, MS Windows uses \ to separate parts of a path (e.g. C:\Program Files\App\), while pretty much all other operating systems use / (e.g. /home/user/script.py)
Python will often convert those automatically, so you can use paths like C:/Program Files/App in Python on Windows as well, but it tends to be a good idea to be safe and use os.path.sep.
Note: if you're on Python 3, you may be better off just using pathlib's Path instead of os.path. It automatically resolves symbolic links (although you can still resolve to the link if you prefer) and has other nice conveniences as well.

Related

Errno 2 No such file or directory: 'user.txt' When there are files in the dictionary [duplicate]

I am trying to open the file recentlyUpdated.yaml from my Python script. But when I try using:
open('recentlyUpdated.yaml')
I get an error that says:
IOError: [Errno 2] No such file or directory: 'recentlyUpdated.yaml'
Why? How can I fix the problem?
Ensure the file exists (and has the right file extension): use os.listdir() to see the list of files in the current working directory.
Ensure you're in the expected directory using os.getcwd().
(If you launch your code from an IDE, you may be in a different directory.)
You can then either:
Call os.chdir(dir) where dir is the directory containing the file. Then, open the file using just its name, e.g. open("file.txt").
Specify an absolute path to the file in your open call.
Use a raw string (r"") if your path uses backslashes, like
so: dir = r'C:\Python32'
If you don't use raw string, you have to escape every backslash: 'C:\\User\\Bob\\...'
Forward-slashes also work on Windows 'C:/Python32' and do not need to be escaped.
Let me clarify how Python finds files:
An absolute path is a path that starts with your computer's root directory, for example C:\Python\scripts if you're on Windows.
A relative path is a path that does not start with your computer's root directory, and is instead relative to something called the working directory. You can view Python's current working directory by calling os.getcwd().
If you try to do open('sortedLists.yaml'), Python will see that you are passing it a relative path, so it will search for the file inside the current working directory.
Calling os.chdir() will change the current working directory.
Example: Let's say file.txt is found in C:\Folder.
To open it, you can do:
os.chdir(r'C:\Folder')
open('file.txt') # relative path, looks inside the current working directory
or
open(r'C:\Folder\file.txt') # absolute path
Most likely, the problem is that you're using a relative file path to open the file, but the current working directory isn't set to what you think it is.
It's a common misconception that relative paths are relative to the location of the python script, but this is untrue. Relative file paths are always relative to the current working directory, and the current working directory doesn't have to be the location of your python script.
You have three options:
Use an absolute path to open the file:
file = open(r'C:\path\to\your\file.yaml')
Generate the path to the file relative to your python script:
from pathlib import Path
script_location = Path(__file__).absolute().parent
file_location = script_location / 'file.yaml'
file = file_location.open()
(See also: How do I get the path and name of the file that is currently executing?)
Change the current working directory before opening the file:
import os
os.chdir(r'C:\path\to\your\file')
file = open('file.yaml')
Other common mistakes that could cause a "file not found" error include:
Accidentally using escape sequences in a file path:
path = 'C:\Users\newton\file.yaml'
# Incorrect! The '\n' in 'Users\newton' is a line break character!
To avoid making this mistake, remember to use raw string literals for file paths:
path = r'C:\Users\newton\file.yaml'
# Correct!
(See also: Windows path in Python)
Forgetting that Windows doesn't display file extensions:
Since Windows doesn't display known file extensions, sometimes when you think your file is named file.yaml, it's actually named file.yaml.yaml. Double-check your file's extension.
The file may be existing but may have a different path. Try writing the absolute path for the file.
Try os.listdir() function to check that atleast python sees the file.
Try it like this:
file1 = open(r'Drive:\Dir\recentlyUpdated.yaml')
Possibly, you closed the 'file1'.
Just use 'w' flag, that create new file:
file1 = open('recentlyUpdated.yaml', 'w')
mode is an optional string that specifies the mode in which the file
is opened. It defaults to 'r' which means open for reading in text
mode. Other common values are 'w' for writing (truncating the file if
it already exists)...
(see also https://docs.python.org/3/library/functions.html?highlight=open#open)
If is VSCode see the workspace. If you are in other workspace this error can rise
Understanding absolute and relative paths
The term path means exactly what it sounds like. It shows the steps that need to be taken, into and out of folders, to find a file. Each step on the path is either a folder name, the special name . (which means the current folder), or the special name .. (which means to go back/out into the parent folder).
The terms absolute and relative also have their usual English meaning. A relative path shows where something is relative to some start point; an absolute path is a location starting from the top.
Paths that start with a path separator, or a drive letter followed by a path separator (like C:/foo) on Windows, are absolute. (On Windows there are also UNC paths, which are necessarily absolute. Most people will never have to worry about these.)
Paths that directly start with a file or folder name, or a drive letter followed directly by the file or folder name (like C:foo) on Windows, are relative.
Understanding the "current working directory"
Relative paths are "relative to" the so-called current working directory (hereafter abbreviated CWD). At the command line, Linux and Mac use a common CWD across all drives. (The entire file system has a common "root", and may include multiple physical storage devices.) Windows is a bit different: it remembers the most recent CWD for each drive, and has separate functionality to switch between drives, restoring those old CWD values.
Each process (this includes terminal/command windows) has its own CWD. When a program is started from the command line, it will get the CWD that the terminal/command process was using. When a program is started from a GUI (by double-clicking a script, or dragging something onto the script, or dragging the script onto a Python executable) or by using an IDE, the CWD might be any number of things depending on the details.
Importantly, the CWD is not necessarily where the script is located.
The script's CWD can be checked using os.getcwd, and modified using os.chdir. Each IDE has its own rules that control the initial CWD; check the documentation for details.
To set the CWD to the folder that contains the current script, determine that path and then set it:
os.chdir(os.path.dirname(os.path.abspath(__file__)))
Verifying the actual file name and path
There are many reasons why the path to a file might not match expectations. For example, sometimes people expect C:/foo.txt on Windows to mean "the file named foo.txt on the desktop". This is wrong. That file is actually - normally - at C:/Users/name/Desktop/foo.txt (replacing name with the current user's username). It could instead be elsewhere, if Windows is configured to put it elsewhere. To find the path to the desktop in a portable way, see How to get Desktop location?.
It's also common to mis-count ..s in a relative path, or inappropriately repeat a folder name in a path. Take special care when constructing a path programmatically. Finally, keep in mind that .. will have no effect while already in a root directory (/ on Linux or Mac, or a drive root on Windows).
Take even more special care when constructing a path based on user input. If the input is not sanitized, bad things could happen (e.g. allowing the user to unzip a file into a folder where it will overwrite something important, or where the user ought not be allowed to write files).
Another common gotcha is that the special ~ shortcut for the current user's home directory does not work in an absolute path specified in a Python program. That part of the path must be explicitly converted to the actual path, using os.path.expanduser. See Why am I forced to os.path.expanduser in python? and os.makedirs doesn't understand "~" in my path.
Keep in mind that os.listdir will give only the file names, not paths. Trying to iterate over a directory listed this way will only work if that directory is the current working directory.
It's also important to make sure of the actual file name. Windows has an option to hide file name extensions in the GUI. If you see foo.txt in a window, it could be that the file's actual name is foo.txt.txt, or something else. You can disable this option in your settings. You can also verify the file name using the command line; dir will tell you the truth about what is in the folder. (The Linux/Mac equivalent is ls, of course; but the problem should not arise there in the first place.)
Backslashes in ordinary strings are escape sequences. This causes problems when trying to a backslash as the path separator on Windows. However, using backslashes for this is not necessary, and generally not advisable. See Windows path in Python.
When trying to create a new file using a file mode like w, the path to the new file still needs to exist - i.e., all the intervening folders. See for example Trying to use open(filename, 'w' ) gives IOError: [Errno 2] No such file or directory if directory doesn't exist. Also keep in mind that the new file name has to be valid. In particular, it will not work to try to insert a date in MM/DD/YYYY format into the file name, because the /s will be treated as path separators.
Check the path that has been mentioned, if it's absolute or relative.
If its something like-->/folder/subfolder/file -->Computer will search for folder in root directory.
If its something like--> ./folder/subfolder/file --> Computer will search for folder in current working directory.
If you are using IDE like VScode, make sure you have opened the IDE from the same directory where you have kept the file you want to access.
For example, if you want to access file.txt which is inside the Document, try opening the IDE from Document by right clicking in the directory and clicking "Open with "

Receiving back a FileNotFoundError and not quite sure why? [duplicate]

I am trying to open the file recentlyUpdated.yaml from my Python script. But when I try using:
open('recentlyUpdated.yaml')
I get an error that says:
IOError: [Errno 2] No such file or directory: 'recentlyUpdated.yaml'
Why? How can I fix the problem?
Ensure the file exists (and has the right file extension): use os.listdir() to see the list of files in the current working directory.
Ensure you're in the expected directory using os.getcwd().
(If you launch your code from an IDE, you may be in a different directory.)
You can then either:
Call os.chdir(dir) where dir is the directory containing the file. Then, open the file using just its name, e.g. open("file.txt").
Specify an absolute path to the file in your open call.
Use a raw string (r"") if your path uses backslashes, like
so: dir = r'C:\Python32'
If you don't use raw string, you have to escape every backslash: 'C:\\User\\Bob\\...'
Forward-slashes also work on Windows 'C:/Python32' and do not need to be escaped.
Let me clarify how Python finds files:
An absolute path is a path that starts with your computer's root directory, for example C:\Python\scripts if you're on Windows.
A relative path is a path that does not start with your computer's root directory, and is instead relative to something called the working directory. You can view Python's current working directory by calling os.getcwd().
If you try to do open('sortedLists.yaml'), Python will see that you are passing it a relative path, so it will search for the file inside the current working directory.
Calling os.chdir() will change the current working directory.
Example: Let's say file.txt is found in C:\Folder.
To open it, you can do:
os.chdir(r'C:\Folder')
open('file.txt') # relative path, looks inside the current working directory
or
open(r'C:\Folder\file.txt') # absolute path
Most likely, the problem is that you're using a relative file path to open the file, but the current working directory isn't set to what you think it is.
It's a common misconception that relative paths are relative to the location of the python script, but this is untrue. Relative file paths are always relative to the current working directory, and the current working directory doesn't have to be the location of your python script.
You have three options:
Use an absolute path to open the file:
file = open(r'C:\path\to\your\file.yaml')
Generate the path to the file relative to your python script:
from pathlib import Path
script_location = Path(__file__).absolute().parent
file_location = script_location / 'file.yaml'
file = file_location.open()
(See also: How do I get the path and name of the file that is currently executing?)
Change the current working directory before opening the file:
import os
os.chdir(r'C:\path\to\your\file')
file = open('file.yaml')
Other common mistakes that could cause a "file not found" error include:
Accidentally using escape sequences in a file path:
path = 'C:\Users\newton\file.yaml'
# Incorrect! The '\n' in 'Users\newton' is a line break character!
To avoid making this mistake, remember to use raw string literals for file paths:
path = r'C:\Users\newton\file.yaml'
# Correct!
(See also: Windows path in Python)
Forgetting that Windows doesn't display file extensions:
Since Windows doesn't display known file extensions, sometimes when you think your file is named file.yaml, it's actually named file.yaml.yaml. Double-check your file's extension.
The file may be existing but may have a different path. Try writing the absolute path for the file.
Try os.listdir() function to check that atleast python sees the file.
Try it like this:
file1 = open(r'Drive:\Dir\recentlyUpdated.yaml')
Possibly, you closed the 'file1'.
Just use 'w' flag, that create new file:
file1 = open('recentlyUpdated.yaml', 'w')
mode is an optional string that specifies the mode in which the file
is opened. It defaults to 'r' which means open for reading in text
mode. Other common values are 'w' for writing (truncating the file if
it already exists)...
(see also https://docs.python.org/3/library/functions.html?highlight=open#open)
If is VSCode see the workspace. If you are in other workspace this error can rise
Understanding absolute and relative paths
The term path means exactly what it sounds like. It shows the steps that need to be taken, into and out of folders, to find a file. Each step on the path is either a folder name, the special name . (which means the current folder), or the special name .. (which means to go back/out into the parent folder).
The terms absolute and relative also have their usual English meaning. A relative path shows where something is relative to some start point; an absolute path is a location starting from the top.
Paths that start with a path separator, or a drive letter followed by a path separator (like C:/foo) on Windows, are absolute. (On Windows there are also UNC paths, which are necessarily absolute. Most people will never have to worry about these.)
Paths that directly start with a file or folder name, or a drive letter followed directly by the file or folder name (like C:foo) on Windows, are relative.
Understanding the "current working directory"
Relative paths are "relative to" the so-called current working directory (hereafter abbreviated CWD). At the command line, Linux and Mac use a common CWD across all drives. (The entire file system has a common "root", and may include multiple physical storage devices.) Windows is a bit different: it remembers the most recent CWD for each drive, and has separate functionality to switch between drives, restoring those old CWD values.
Each process (this includes terminal/command windows) has its own CWD. When a program is started from the command line, it will get the CWD that the terminal/command process was using. When a program is started from a GUI (by double-clicking a script, or dragging something onto the script, or dragging the script onto a Python executable) or by using an IDE, the CWD might be any number of things depending on the details.
Importantly, the CWD is not necessarily where the script is located.
The script's CWD can be checked using os.getcwd, and modified using os.chdir. Each IDE has its own rules that control the initial CWD; check the documentation for details.
To set the CWD to the folder that contains the current script, determine that path and then set it:
os.chdir(os.path.dirname(os.path.abspath(__file__)))
Verifying the actual file name and path
There are many reasons why the path to a file might not match expectations. For example, sometimes people expect C:/foo.txt on Windows to mean "the file named foo.txt on the desktop". This is wrong. That file is actually - normally - at C:/Users/name/Desktop/foo.txt (replacing name with the current user's username). It could instead be elsewhere, if Windows is configured to put it elsewhere. To find the path to the desktop in a portable way, see How to get Desktop location?.
It's also common to mis-count ..s in a relative path, or inappropriately repeat a folder name in a path. Take special care when constructing a path programmatically. Finally, keep in mind that .. will have no effect while already in a root directory (/ on Linux or Mac, or a drive root on Windows).
Take even more special care when constructing a path based on user input. If the input is not sanitized, bad things could happen (e.g. allowing the user to unzip a file into a folder where it will overwrite something important, or where the user ought not be allowed to write files).
Another common gotcha is that the special ~ shortcut for the current user's home directory does not work in an absolute path specified in a Python program. That part of the path must be explicitly converted to the actual path, using os.path.expanduser. See Why am I forced to os.path.expanduser in python? and os.makedirs doesn't understand "~" in my path.
Keep in mind that os.listdir will give only the file names, not paths. Trying to iterate over a directory listed this way will only work if that directory is the current working directory.
It's also important to make sure of the actual file name. Windows has an option to hide file name extensions in the GUI. If you see foo.txt in a window, it could be that the file's actual name is foo.txt.txt, or something else. You can disable this option in your settings. You can also verify the file name using the command line; dir will tell you the truth about what is in the folder. (The Linux/Mac equivalent is ls, of course; but the problem should not arise there in the first place.)
Backslashes in ordinary strings are escape sequences. This causes problems when trying to a backslash as the path separator on Windows. However, using backslashes for this is not necessary, and generally not advisable. See Windows path in Python.
When trying to create a new file using a file mode like w, the path to the new file still needs to exist - i.e., all the intervening folders. See for example Trying to use open(filename, 'w' ) gives IOError: [Errno 2] No such file or directory if directory doesn't exist. Also keep in mind that the new file name has to be valid. In particular, it will not work to try to insert a date in MM/DD/YYYY format into the file name, because the /s will be treated as path separators.
Check the path that has been mentioned, if it's absolute or relative.
If its something like-->/folder/subfolder/file -->Computer will search for folder in root directory.
If its something like--> ./folder/subfolder/file --> Computer will search for folder in current working directory.
If you are using IDE like VScode, make sure you have opened the IDE from the same directory where you have kept the file you want to access.
For example, if you want to access file.txt which is inside the Document, try opening the IDE from Document by right clicking in the directory and clicking "Open with "

Directory and path said to exist, but not appearing when using terminal to access directory (python)? [duplicate]

My book states:
Every program that runs on your computer has a current working directory, or cwd. Any filenames or paths that do not begin with the root folder are assumed to be under the current working directory
As I am on OSX, my root folder is /. When I type in os.getcwd() in my Python shell, I get /Users/apple/Documents. Why am I getting the Documents folder in my cwd? Is it saying that Python is using Documents folder? Isn't there any path heading to Python that begins with / (the root folder)? Also, does every program have a different cwd?
Every process has a current directory. When a process starts, it simply inherits the current directory from its parent process; and it's not, for example, set to the directory which contains the program you are running.
For a more detailed explanation, read on.
When disks became large enough that you did not want all your files in the same place, operating system vendors came up with a way to structure files in directories. So instead of saving everything in the same directory (or "folder" as beginners are now taught to call it) you could create new collections and other new collections inside of those (except in some early implementations directories could not contain other directories!)
Fundamentally, a directory is just a peculiar type of file, whose contents is a collection of other files, which can also include other directories.
On a primitive operating system, that was where the story ended. If you wanted to print a file called term_paper.txt which was in the directory spring_semester which in turn was in the directory 2021 which was in the directory studies in the directory mine, you would have to say
print mine/studies/2021/spring_semester/term_paper.txt
(except the command was probably something more arcane than print, and the directory separator might have been something crazy like square brackets and colons, or something;
lpr [mine:studies:2021:spring_semester]term_paper.txt
but this is unimportant for this exposition) and if you wanted to copy the file, you would have to spell out the whole enchilada twice:
copy mine/studies/2021/spring_semester/term_paper.txt mine/studies/2021/spring_semester/term_paper.backup
Then came the concept of a current working directory. What if you could say "from now on, until I say otherwise, all the files I am talking about will be in this particular directory". Thus was the cd command born (except on old systems like VMS it was called something clunkier, like SET DEFAULT).
cd mine/studies/2021/spring_semester
print term_paper.txt
copy term_paper.txt term_paper.backup
That's really all there is to it. When you cd (or, in Python, os.chdir()), you change your current working directory. It stays until you log out (or otherwise exit this process), or until you cd to a different working directory, or switch to a different process or window where you are running a separate command which has its own current working directory. Just like you can have your file browser (Explorer or Finder or Nautilus or whatever it's called) open with multiple windows in different directories, you can have multiple terminals open, and each one runs a shell which has its own independent current working directory.
So when you type pwd into a terminal (or cwd or whatever the command is called in your command language) the result will pretty much depend on what you happened to do in that window or process before, and probably depends on how you created that window or process. On many Unix-like systems, when you create a new terminal window with an associated shell process, it is originally opened in your home directory (/home/you on many Unix systems, /Users/you on a Mac, something more or less like C:\Users\you on recent Windows) though probably your terminal can be configured to open somewhere else (commonly Desktop or Documents inside your home directory on some ostensibly "modern" and "friendly" systems).
Many beginners have a vague and incomplete mental model of what happens when you run a program. Many will incessantly cd into whichever directory contains their script or program, and be genuinely scared and confused when you tell them that you don't have to. If frobozz is in /home/you/bin then you don't have to
cd /home/you/bin
./frobozz
because you can simply run it directly with
/home/you/bin/frobozz
and similarly if ls is in /bin you most definitely don't
cd /bin
./ls
just to get a directory listing.
Furthermore, like the ls (or on Windows, dir) example should readily convince you, any program you run will look in your current directory for files. Not the directory the program or script was saved in. Because if that were the case, ls could only produce a listing of the directory it's in (/bin) -- there is nothing special about the directory listing program, or the copy program, or the word processor program; they all, by design, look in the current working directory (though again, some GUI programs will start with e.g. your Documents directory as their current working directory, by design, at least if you don't tell them otherwise).
Many beginners write scripts which demand that the input and output files are in a particular directory inside a particular user's home directory, but this is just poor design; a well-written program will simply look in the current working directory for its input files unless instructed otherwise, and write output to the current directory (or perhaps create a new directory in the current directory for its output if it consists of multiple files).
Python, then, is no different from any other programs. If your current working directory is /Users/you/Documents when you run python then that directory is what os.getcwd() inside your Python script or interpreter will produce (unless you separately os.chdir() to a different directory during runtime; but again, this is probably unnecessary, and often a sign that a script was written by a beginner). And if your Python script accepts a file name parameter, it probably should simply get the operating system to open whatever the user passed in, which means relative file names are relative to the invoking user's current working directory.
python /home/you/bin/script.py file.txt
should simply open(sys.argv[1]) and fail with an error if file.txt does not exist in the current directory. Let's say that again; it doesn't look in /home/you/bin for file.txt -- unless of course that is also the current working directory of you, the invoking user, in which case of course you could simply write
python script.py file.txt
On a related note, many beginners needlessly try something like
with open(os.path.join(os.getcwd(), "input.txt")) as data:
...
which needlessly calls os.getcwd(). Why is it needless? If you have been following along, you know the answer already: the operating system will look for relative file names (like here, input.txt) in the current working directory anyway. So all you need is
with open("input.txt") as data:
...
One final remark. On Unix-like systems, all files are ultimately inside the root directory / which contains a number of other directories (and usually regular users are not allowed to write anything there, and system administrators with the privilege to do it typically don't want to). Every relative file name can be turned into an absolute file name by tracing the path from the root directory to the current directory. So if the file we want to access is in /home/you/Documents/file.txt it means that home is in the root directory, and contains you, which contains Documents, which contains file.txt. If your current working directory were /home you could refer to the same file by the relative path you/Documents/file.txt; and if your current directory was /home/you, the relative path to it would be Documents/file.txt (and if your current directory was /home/you/Music you could say ../Documents/file.txt but let's not take this example any further now).
Windows has a slightly different arrangement, with a number of drives with single-letter identifiers, each with its own root directory; so the root of the C: drive is C:\ and the root of the D: drive is D:\ etc. (and the directory separator is a backslash instead of a slash, although you can use a slash instead pretty much everywhere, which is often a good idea for preserving your sanity).
Your python interpreter location is based off of how you launched it, as well as subsequent actions taken after launching it like use of the os module to navigate your file system. Merely starting the interpreter will place you in the directory of your python installation (not the same on different operating systems). On the other hand, if you start by editing or running a file within a specific directory, your location will be the folder of the file you were editing. If you need to run the interpreter in a certain directory and you are using idle for example, it is easiest to start by creating a python file there one way or another and when you edit it you can start a shell with Run > Python Shell which will already be in that directory. If you are using the command line interpreter, navigate to the folder where you want to run your interpreter before running the python/python3/py command. If you need to navigate manually, you can of course use the following which has already been mentioned:
import os
os.chdir('full_path_to_your_directory')
This has nothing to do with osx in particular, it's more of a concept shared by all unix-based systems, and I believe Windows as well. os.getcwd() is the equivalent of the bash pwd command - it simply returns the full path of the current location in which you are in. In other words:
alex#suse:~> cd /
alex#suse:/> python
Python 2.7.12 (default, Jul 01 2016, 15:34:22) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getcwd()
'/'
It depends from where you started the python shell/script.
Python is usually (except if you are working with virtual environments) accessible from any of your directory. You can check the variables in your path and Python should be available. So the directory you get when you ask Python is the one in which you started Python. Change directory in your shell before starting Python and you will see you will it.
os.getcwd() has nothing to do with OSX in particular. It simply returns the directory/location of the source-file. If my source-file is on my desktop it would return C:\Users\Dave\Desktop\ or let say the source-file is saved on an external storage device it could return something like G:\Programs\. It is the same for both unix-based and Windows systems.

Popen with conflicting executable/path

I'd like to call the "convert" utility from ImageMagick from my Python script using Popen, like so:
Popen(["convert", input_path, "-flop", output_file_path])
(The above example simply reverses the image horizontally)
The problem is that when I run the script in Windows, it mistakenly calls the convert.exe utility that ships with Windows to convert FAT partitions to NTFS! (located in \Windows\system32)
Now, if I randomly open a command prompt at any directory other than system32, and type "convert", it correctly runs the ImageMagick executable. So, this implies that Popen is automatically looking in system32. How can I make it not look in system32, and run the correct executable?
Search for a program is not trivial. I'd specify the full path to the convert.exe executable explicitly instead.
subprocess uses CreateProcess on Windows that looks in system32 directory even before any other directory in %PATH%:
... If the file name does not contain an extension, .exe is appended.
Therefore, if the file name extension is .com, this parameter must
include the .com extension. If the file name ends in a period (.) with
no extension, or if the file name contains a path, .exe is not
appended. If the file name does not contain a directory path, the
system searches for the executable file in the following sequence:
The directory from which the application loaded.
The current directory for the parent process.
The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.
Therefore convert is equivalent to convert.exe in this case. It first looks in a directory that contains sys.executable e.g., C:\Python27. Then in the current directory: where you started the Python script from. Then in system32 where it finds convert.exe (filesystem utility, not imagemagick).
You could try to remove system32 directory from os.environ['PATH'] it may(?) suppress checking it: Popen(cmd, env=no_system32_environ) but it is fragile (worse than the explicit path).
There is a related issue on Python bug tracker: "Subprocess picks the wrong executable on Windows."
cmd.exe (the shell) uses different algorithm. See How does Windows locate files input in the shell?
If you set shell=True then the search sequence for convert program:
convert is not an internal shell command
there is no explicit path, so the search continues
search the current directory
search each directory specified by the PATH environment variable, in the order listed
%PATHEXT% defines which file extensions are checked and in what order e.g., convert.com, convert.exe, convert.bat, convert.cmd if %PATHEXT% is .com;.exe;.bat;.cmd.
As a completely different approach, you may want to try out PythonMagick, a Python wrapper for ImageMagick. This way you can access convert's functions from within Python, and you won't have to spawn outside processes.
Just ran into this myself. Running a php script in a shell has access to the shell $PATH, while running within Apache does not (at least not a $PATH with the Cygwin dll/exe).
Secondly, use the native Windows notation C:/dir/subdir/pgm within php when on a windows platform and you will get what you expect.
So multi-platform code needs to switch/case the pathing and then reference the decision.

open() gives FileNotFoundError / IOError: '[Errno 2] No such file or directory'

I am trying to open the file recentlyUpdated.yaml from my Python script. But when I try using:
open('recentlyUpdated.yaml')
I get an error that says:
IOError: [Errno 2] No such file or directory: 'recentlyUpdated.yaml'
Why? How can I fix the problem?
Ensure the file exists (and has the right file extension): use os.listdir() to see the list of files in the current working directory.
Ensure you're in the expected directory using os.getcwd().
(If you launch your code from an IDE, you may be in a different directory.)
You can then either:
Call os.chdir(dir) where dir is the directory containing the file. Then, open the file using just its name, e.g. open("file.txt").
Specify an absolute path to the file in your open call.
Use a raw string (r"") if your path uses backslashes, like
so: dir = r'C:\Python32'
If you don't use raw string, you have to escape every backslash: 'C:\\User\\Bob\\...'
Forward-slashes also work on Windows 'C:/Python32' and do not need to be escaped.
Let me clarify how Python finds files:
An absolute path is a path that starts with your computer's root directory, for example C:\Python\scripts if you're on Windows.
A relative path is a path that does not start with your computer's root directory, and is instead relative to something called the working directory. You can view Python's current working directory by calling os.getcwd().
If you try to do open('sortedLists.yaml'), Python will see that you are passing it a relative path, so it will search for the file inside the current working directory.
Calling os.chdir() will change the current working directory.
Example: Let's say file.txt is found in C:\Folder.
To open it, you can do:
os.chdir(r'C:\Folder')
open('file.txt') # relative path, looks inside the current working directory
or
open(r'C:\Folder\file.txt') # absolute path
Most likely, the problem is that you're using a relative file path to open the file, but the current working directory isn't set to what you think it is.
It's a common misconception that relative paths are relative to the location of the python script, but this is untrue. Relative file paths are always relative to the current working directory, and the current working directory doesn't have to be the location of your python script.
You have three options:
Use an absolute path to open the file:
file = open(r'C:\path\to\your\file.yaml')
Generate the path to the file relative to your python script:
from pathlib import Path
script_location = Path(__file__).absolute().parent
file_location = script_location / 'file.yaml'
file = file_location.open()
(See also: How do I get the path and name of the file that is currently executing?)
Change the current working directory before opening the file:
import os
os.chdir(r'C:\path\to\your\file')
file = open('file.yaml')
Other common mistakes that could cause a "file not found" error include:
Accidentally using escape sequences in a file path:
path = 'C:\Users\newton\file.yaml'
# Incorrect! The '\n' in 'Users\newton' is a line break character!
To avoid making this mistake, remember to use raw string literals for file paths:
path = r'C:\Users\newton\file.yaml'
# Correct!
(See also: Windows path in Python)
Forgetting that Windows doesn't display file extensions:
Since Windows doesn't display known file extensions, sometimes when you think your file is named file.yaml, it's actually named file.yaml.yaml. Double-check your file's extension.
The file may be existing but may have a different path. Try writing the absolute path for the file.
Try os.listdir() function to check that atleast python sees the file.
Try it like this:
file1 = open(r'Drive:\Dir\recentlyUpdated.yaml')
Possibly, you closed the 'file1'.
Just use 'w' flag, that create new file:
file1 = open('recentlyUpdated.yaml', 'w')
mode is an optional string that specifies the mode in which the file
is opened. It defaults to 'r' which means open for reading in text
mode. Other common values are 'w' for writing (truncating the file if
it already exists)...
(see also https://docs.python.org/3/library/functions.html?highlight=open#open)
If is VSCode see the workspace. If you are in other workspace this error can rise
Understanding absolute and relative paths
The term path means exactly what it sounds like. It shows the steps that need to be taken, into and out of folders, to find a file. Each step on the path is either a folder name, the special name . (which means the current folder), or the special name .. (which means to go back/out into the parent folder).
The terms absolute and relative also have their usual English meaning. A relative path shows where something is relative to some start point; an absolute path is a location starting from the top.
Paths that start with a path separator, or a drive letter followed by a path separator (like C:/foo) on Windows, are absolute. (On Windows there are also UNC paths, which are necessarily absolute. Most people will never have to worry about these.)
Paths that directly start with a file or folder name, or a drive letter followed directly by the file or folder name (like C:foo) on Windows, are relative.
Understanding the "current working directory"
Relative paths are "relative to" the so-called current working directory (hereafter abbreviated CWD). At the command line, Linux and Mac use a common CWD across all drives. (The entire file system has a common "root", and may include multiple physical storage devices.) Windows is a bit different: it remembers the most recent CWD for each drive, and has separate functionality to switch between drives, restoring those old CWD values.
Each process (this includes terminal/command windows) has its own CWD. When a program is started from the command line, it will get the CWD that the terminal/command process was using. When a program is started from a GUI (by double-clicking a script, or dragging something onto the script, or dragging the script onto a Python executable) or by using an IDE, the CWD might be any number of things depending on the details.
Importantly, the CWD is not necessarily where the script is located.
The script's CWD can be checked using os.getcwd, and modified using os.chdir. Each IDE has its own rules that control the initial CWD; check the documentation for details.
To set the CWD to the folder that contains the current script, determine that path and then set it:
os.chdir(os.path.dirname(os.path.abspath(__file__)))
Verifying the actual file name and path
There are many reasons why the path to a file might not match expectations. For example, sometimes people expect C:/foo.txt on Windows to mean "the file named foo.txt on the desktop". This is wrong. That file is actually - normally - at C:/Users/name/Desktop/foo.txt (replacing name with the current user's username). It could instead be elsewhere, if Windows is configured to put it elsewhere. To find the path to the desktop in a portable way, see How to get Desktop location?.
It's also common to mis-count ..s in a relative path, or inappropriately repeat a folder name in a path. Take special care when constructing a path programmatically. Finally, keep in mind that .. will have no effect while already in a root directory (/ on Linux or Mac, or a drive root on Windows).
Take even more special care when constructing a path based on user input. If the input is not sanitized, bad things could happen (e.g. allowing the user to unzip a file into a folder where it will overwrite something important, or where the user ought not be allowed to write files).
Another common gotcha is that the special ~ shortcut for the current user's home directory does not work in an absolute path specified in a Python program. That part of the path must be explicitly converted to the actual path, using os.path.expanduser. See Why am I forced to os.path.expanduser in python? and os.makedirs doesn't understand "~" in my path.
Keep in mind that os.listdir will give only the file names, not paths. Trying to iterate over a directory listed this way will only work if that directory is the current working directory.
It's also important to make sure of the actual file name. Windows has an option to hide file name extensions in the GUI. If you see foo.txt in a window, it could be that the file's actual name is foo.txt.txt, or something else. You can disable this option in your settings. You can also verify the file name using the command line; dir will tell you the truth about what is in the folder. (The Linux/Mac equivalent is ls, of course; but the problem should not arise there in the first place.)
Backslashes in ordinary strings are escape sequences. This causes problems when trying to a backslash as the path separator on Windows. However, using backslashes for this is not necessary, and generally not advisable. See Windows path in Python.
When trying to create a new file using a file mode like w, the path to the new file still needs to exist - i.e., all the intervening folders. See for example Trying to use open(filename, 'w' ) gives IOError: [Errno 2] No such file or directory if directory doesn't exist. Also keep in mind that the new file name has to be valid. In particular, it will not work to try to insert a date in MM/DD/YYYY format into the file name, because the /s will be treated as path separators.
Check the path that has been mentioned, if it's absolute or relative.
If its something like-->/folder/subfolder/file -->Computer will search for folder in root directory.
If its something like--> ./folder/subfolder/file --> Computer will search for folder in current working directory.
If you are using IDE like VScode, make sure you have opened the IDE from the same directory where you have kept the file you want to access.
For example, if you want to access file.txt which is inside the Document, try opening the IDE from Document by right clicking in the directory and clicking "Open with "

Categories

Resources