2

Python version: 2.6.6

I'm trying to use Python to create a file that doesn't exist by using open('file/path/file_name', 'w'). However, I can't hard code the file path in like that since I need to pass it in as a variable containing a path specified by the user.

This works: open('/home/root/my_file.txt', 'w')

But my code doesn't:

import os
import sys

input = sys.argv[1] # assume it's "/home/root"
path = os.path.join(input, "my_file.txt")
f = open(path, 'w')

Which causes an exception IOError: [Errno 2] No such file or directory: '/home/root/my_file.txt'

I've also tried some other modes other than "w", like "w+" and "a", but none of them worked.

Could anyone tell me how I can fix this problem? Is it caused by the my incorrect way of using it or is it because of the version of Python I'm using?

Thanks.

UPDATE:

I have found the solution to my problem: my carelessness of forgetting to create the directory which doesn't exist yet. Here's my final code:

import os, errno
import sys

input = sys.argv[1]

try:
    os.makedirs(input)
except OSError as e:
    if e.errno == errno.EEXIST and os.path.isdir(input):
        pass
    else:
        raise

path = os.path.join(input, "my_file.txt")
with open(path, "w") as f:
    f.write("content")

Code adapted from this SO answer

Community
  • 1
  • 1
user14412
  • 987
  • 1
  • 11
  • 32
  • 1
    That code isn't runnable; you don't import `sys`. Can you fix it, then run it and copy-paste the exact, full stack trace? – user2357112 Aug 06 '13 at 01:17
  • @user2357112: sorry about that. The full stack trace contains only the IOError. – user14412 Aug 06 '13 at 02:02
  • Are you sure /home/root exists and you write rights? Linux typically has a /root and its not writable by regular users. – tdelaney Aug 06 '13 at 02:04
  • No, it has to contain some module, function, and line number information as well. (Partly, I want the stack trace to make sure you aren't copying the exception from memory or by retyping it, but the other information is also useful.) – user2357112 Aug 06 '13 at 02:05
  • @tdelaney: You are right... I realized the directory doesn't exist. `os.makedirs` solved the problem. – user14412 Aug 06 '13 at 02:18
  • @user2357112: I didn't retype that exception from memory, that was copied from the terminal. Thanks for your patience. – user14412 Aug 06 '13 at 02:21
  • Well, `/home/root` really doesn't seem like the kind of directory your script should be creating if it doesn't already exist… But if you're happy with the solution, OK. – abarnert Aug 06 '13 at 02:23
  • @abarnert: don't worry, I'm not actually create the directory `/home/root`, that's just used as an example. Thanks for the heads up though – user14412 Aug 06 '13 at 02:30

1 Answers1

4

When you use a relative path, like this:

open('file/path/file_name', 'w')

That's equivalent to taking the current working directory, appending /file/path/file_name, and trying to open or create a file at that location.

So, if there is no file directory under the current working directory, or there is a file directory but it has no path directory underneath it, you will get this error.

If you want to create the directory if it doesn't exist, then create the file underneath it, you need to do that explicitly:

os.makedirs('file/path')
open('file/path/file_name', 'w')

For debugging cases like this, it may be helpful to print out the absolute path to the file you're trying to open:

print input
print os.path.abspath(input)

This may be, say, /home/root/file/path/file_name. If that was what you expected, then you can check (in your terminal or GUI) whether /home/root/file/path already exists. If it wasn't what you expected, then your current working directory may not be what you wanted it to be.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • I always learned that you are supposed to do `os.makedirs(os.path.relpath(...))`. Can you tell me what the difference is? – 2rs2ts Aug 06 '13 at 01:26
  • 1
    @2rs2ts: The big issue is that if you're passing it a path that may include `..` somewhere, you may end up badly confusing things. Using either `abspath` or `relpath` solves that. The advantage of `relpath` is that it gives you an easy way to verify that the path is actually a subdirectory of the CWD or specified `start`, which can be useful for security reasons. But with a literal path… you don't need either, just don't put any `..`s in or create directories where you want to prevent directories from being created. :) – abarnert Aug 06 '13 at 01:39
  • @2rs2ts: By the way, I'm not sure _exactly_ what "badly confusing things" means, but I assume the issue is with using `mkdirs('foo/../bar')` where `foo` may be a symlink; `bar` could then end up created alongside `foo`, or alongside `foo`'s target, and it's difficult to predict in advance. – abarnert Aug 06 '13 at 01:56
  • Thanks for your answer. I did indeed forget to make that directory. I'll update my question to include my final code. – user14412 Aug 06 '13 at 02:22