Reputation: 61635
If your question was closed as a duplicate of this, it is because you have code along the lines of:
from os import *
with open('example.txt', mode='r') as f:
print('successfully opened example.txt')
This causes an error message that says TypeError: open() missing required argument 'flags' (pos 2)
.
Alternately, you may have tried specifying the mode
as a positional argument instead of a keyword argument, like:
from os import *
with open('example.txt', 'r') as f:
print('successfully opened example.txt')
But that does not work either - it gives a different error, which says TypeError: an integer is required (got type str)
.
You may have noticed that there is no such keyword argument flags
for the built-in open
function:
>>> help(open)
Help on built-in function open in module io:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
Open file and return a stream. Raise OSError upon failure.
Indeed, if you try removing from os import *
from the code example, you should find that the problem is resolved.
This question is an artificial canonical duplicate, to explain what happened, i.e.: Why is it different when the code says from os import *
? Also, how can the problem be resolved?
Upvotes: 1
Views: 2150
Reputation: 61635
Using a star import like from os import *
- or explicitly using from os import open
, or perhaps taking some more indirect route - means that the name open
will no longer refer to the built-in open
function (which is also available from the io
standard library module), but instead to os.open
.1
This function is also used for opening files, but it provides a lower-level interface. It offers more options for controlling how the file is opened.
In particular: the flags
argument here is analogous to the mode
used by the built-in open
, but it offers many more options (most of which are platform-specific). Rather than a string, it should be an integer produced by bitwise-OR of some flag values (i.e., it directly reflects a C interface). The mode
argument, on the other hand, indicates the (UNIX-like file system) permissions that will be used when creating a new file, if open
should create one.
Again: normal code should not use this, but instead use the built-in open
. (To fix the file permissions after creating a new file, use os.chmod
.)
To avoid this name collision, simply don't use star-imports and don't import open
explicitly. Instead, if os
standard library module functionality is needed, just import os
and then use qualified names.
At the interpreter prompt, del open
will get rid of the global binding of the name open
, making the builtin one visible again. Alternately, since the built-in open
is the same function as the built-in open
(not simply another function doing the same thing, but literally the same object), we can re-import that name: from io import open
. These techniques would also work within a script that did from os import *
after that import, but it will be much cleaner and less error-prone in the long run to just avoid star-imports.
1 Keep in mind that a name can only refer to one thing at a time. See also: Short description of the scoping rules? and Why does code like `str = str(...)` cause a TypeError, but only the second time?.
Upvotes: 1