If the reason you're checking is so you can do something like if file_exists: open_it()
, it's safer to use a try
around the attempt to open it. Checking and then opening risks the file being deleted or moved or something between when you check and when you try to open it.
If you're not planning to open the file immediately, you can use os.path.isfile
Return True
if path is an existing regular file. This follows symbolic links, so both islink() and isfile() can be true for the same path.
import os.path
os.path.isfile(fname)
if you need to be sure it's a file.
Starting with Python 3.4, the pathlib
module offers an object-oriented approach (backported to pathlib2
in Python 2.7):
from pathlib import Path
my_file = Path("/path/to/file")
if my_file.is_file():
# file exists
To check a directory, do:
if my_file.is_dir():
# directory exists
To check whether a Path
object exists independently of whether is it a file or directory, use exists()
:
if my_file.exists():
# path exists
You can also use resolve(strict=True)
in a try
block:
try:
my_abs_path = my_file.resolve(strict=True)
except FileNotFoundError:
# doesn't exist
else:
# exists
shutil
has many methods you can use. One of which is:
from shutil import copyfile
copyfile(src, dst)
# 2nd option
copy(src, dst) # dst can be a folder; use copy2() to preserve timestamp
- Copy the contents of the file named
src
to a file named dst
. Both src
and dst
need to be the entire filename of the files, including path.
- The destination location must be writable; otherwise, an
IOError
exception will be raised.
- If
dst
already exists, it will be replaced.
- Special files such as character or block devices and pipes cannot be copied with this function.
- With
copy
, src
and dst
are path names given as str
s.
Another shutil
method to look at is shutil.copy2()
. It's similar but preserves more metadata (e.g. time stamps).
If you use os.path
operations, use copy
rather than copyfile
. copyfile
will only accept strings.
Best Answer
TL;DR
while(!feof)
is wrong because it tests for something that is irrelevant and fails to test for something that you need to know. The result is that you are erroneously executing code that assumes that it is accessing data that was read successfully, when in fact this never happened.I'd like to provide an abstract, high-level perspective. So continue reading if you're interested in what
while(!feof)
actually does.Concurrency and simultaneity
I/O operations interact with the environment. The environment is not part of your program, and not under your control. The environment truly exists "concurrently" with your program. As with all things concurrent, questions about the "current state" don't make sense: There is no concept of "simultaneity" across concurrent events. Many properties of state simply don't exist concurrently.
Let me make this more precise: Suppose you want to ask, "do you have more data". You could ask this of a concurrent container, or of your I/O system. But the answer is generally unactionable, and thus meaningless. So what if the container says "yes" – by the time you try reading, it may no longer have data. Similarly, if the answer is "no", by the time you try reading, data may have arrived. The conclusion is that there simply is no property like "I have data", since you cannot act meaningfully in response to any possible answer. (The situation is slightly better with buffered input, where you might conceivably get a "yes, I have data" that constitutes some kind of guarantee, but you would still have to be able to deal with the opposite case. And with output the situation is certainly just as bad as I described: you never know if that disk or that network buffer is full.)
So we conclude that it is impossible, and in fact unreasonable, to ask an I/O system whether it will be able to perform an I/O operation. The only possible way we can interact with it (just as with a concurrent container) is to attempt the operation and check whether it succeeded or failed. At that moment where you interact with the environment, then and only then can you know whether the interaction was actually possible, and at that point you must commit to performing the interaction. (This is a "synchronisation point", if you will.)
EOF
Now we get to EOF. EOF is the response you get from an attempted I/O operation. It means that you were trying to read or write something, but when doing so you failed to read or write any data, and instead the end of the input or output was encountered. This is true for essentially all the I/O APIs, whether it be the C standard library, C++ iostreams, or other libraries. As long as the I/O operations succeed, you simply cannot know whether further, future operations will succeed. You must always first try the operation and then respond to success or failure.
Examples
In each of the examples, note carefully that we first attempt the I/O operation and then consume the result if it is valid. Note further that we always must use the result of the I/O operation, though the result takes different shapes and forms in each example.
C stdio, read from a file:
The result we must use is
n
, the number of elements that were read (which may be as little as zero).C stdio,
scanf
:The result we must use is the return value of
scanf
, the number of elements converted.C++, iostreams formatted extraction:
The result we must use is
std::cin
itself, which can be evaluated in a boolean context and tells us whether the stream is still in thegood()
state.C++, iostreams getline:
The result we must use is again
std::cin
, just as before.POSIX,
write(2)
to flush a buffer:The result we use here is
k
, the number of bytes written. The point here is that we can only know how many bytes were written after the write operation.POSIX
getline()
The result we must use is
nbytes
, the number of bytes up to and including the newline (or EOF if the file did not end with a newline).Note that the function explicitly returns
-1
(and not EOF!) when an error occurs or it reaches EOF.You may notice that we very rarely spell out the actual word "EOF". We usually detect the error condition in some other way that is more immediately interesting to us (e.g. failure to perform as much I/O as we had desired). In every example there is some API feature that could tell us explicitly that the EOF state has been encountered, but this is in fact not a terribly useful piece of information. It is much more of a detail than we often care about. What matters is whether the I/O succeeded, more-so than how it failed.
A final example that actually queries the EOF state: Suppose you have a string and want to test that it represents an integer in its entirety, with no extra bits at the end except whitespace. Using C++ iostreams, it goes like this:
We use two results here. The first is
iss
, the stream object itself, to check that the formatted extraction tovalue
succeeded. But then, after also consuming whitespace, we perform another I/O/ operation,iss.get()
, and expect it to fail as EOF, which is the case if the entire string has already been consumed by the formatted extraction.In the C standard library you can achieve something similar with the
strto*l
functions by checking that the end pointer has reached the end of the input string.