I'm wondering what is going on with the file open() mode validation (Python2.7):
>>> with open('input.txt', 'illegal') as f:
... for line in f:
... print line
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: mode string must begin with one of 'r', 'w', 'a' or 'U', not 'illegal'
>>> with open('input.txt', 'rock&roll') as f:
... for line in f:
... print line
...
1
2
3
So, I cannot open the file in illegal mode, but I can open it in rock&roll mode. What mode is actually used for opening the file in this case?
Note that on python3 I cannot use both illegal and rock&roll:
>>> with open('input.txt', 'rock&roll') as f:
... for line in f:
... print(line)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid mode: 'rock&roll'
>>> with open('input.txt', 'illegal') as f:
... for line in f:
... print(line)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid mode: 'illegal'
And, this is confusing, why the behavior is different for python3.x?
The Python 2.x open function essentially delegates its work to the C library fopen function. On my system, the documentation for fopen contains:
The argument mode points to a string beginning with one of the following sequences (Additional characters may follow these sequences.):
Your ock&roll is considered "additional characters".
In Python 3, the allowed open modes are more restricted (essentially, only valid strings are permitted).
The previous traceback explains it nicely:
"ValueError: mode string must begin with one of 'r', 'w', 'a' or 'U'"
"rock&roll" begins with "r", so it's apparently legal.
Related
I often use print() instead of file.write() when writing to files in Python. Recently, I had to write out some binary data, and tried a similar pattern:
f = open('test.txt', 'w')
f.write('abcd')
print('efgh', file=f)
f.close()
f = open('test.bin', 'wb')
f.write(b'abcd') # works as expected
print(b'efgh', file=f)
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: a bytes-like object is required, not 'str'
f.close()
My first thought was the default newline-appending behaivor of print() might be at fault:
print(b'efgh', file=f, end='')
# same error
print(b'efgh', file=f, end=None)
# same error
print(b'efgh', file=f, end=b'')
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: end must be None or a string, not bytes
print(b'efgh', file=f, end=b'\n')
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: end must be None or a string, not bytes
Unfortunately, none of the permutations of changing the end worked.
Why is this happening? I suspect that this use of print() might not be supported, but in that case the error message is quite confusing.
From python3 documentation: https://docs.python.org/3/library/functions.html#print
All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values. If no objects are given, print() will just write end.
As I understand, you can't write bytes with print() because the object you want to write is passed only as positional argument and positional arguments are converted to strings(hence the error).
While writing some tests, i got stuck on some weird behavior. I finally narrow the problem to file opening. For instance, this one, my.dat:
one line
two lines and no final line break
I then ran that python code:
with open('my.dat') as fd:
assert fd.read()[-1] == '\n'
With both python 3 and 2, this code does not raise any AssertError.
My question is: why forcing the presence of line jump at the end of files ?
It works here. Are you 100% sure that there is not actually a newline at the end of your file? Because many text editors (atom, notepad++) automatically add newlines at the end of a file.
>>> open('a.txt', 'w').write('blabla')
6
>>> open('a.txt', 'r').read()
'blabla'
>>> assert open('a.txt', 'r').read()[-1] == '\n'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
I am trying to read a file path using config parser and later read from that file
>>> cfg_file = './crawler.config'
>>> config = SafeConfigParser()
>>> config.read(cfg_file)
['./crawler.config']
>>> f = config.get('default', 'sites_file')
>>> with open(f) as fp:
... print fp.read()
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: u'"/home/avi/src/typo.csv"'
>>>
I think there is a problem with the Unicode. I can't figure out a solution. If I pass the filename directly as a string it works fine. Any help in resolving this would be appreciated.
Try changing the value of 'sites_file' in the config to /home/avi/src/typo.csv from "/home/avi/src/typo.csv"
or:
Replace the quotes before opening the file.
Ex:
with open(f.replace('"', '')) as fp:
print fp.read()
f = config.get('default', 'sites_file')
may be f's value will be "/home/avi/src/typo.csv"
which does not exist
with open(f) as fp:
print fp.read()
You are trying to read a non existing file
The documentation reads:
ast.parse(source, filename='<unknown>', mode='exec')
Equivalent to compile(source, filename, mode, ast.PyCF_ONLY_AST).
compile(source, filename, mode[, flags[, dont_inherit]])
The filename argument should give the file from which the code was read;
pass some recognizable value if it wasn’t read from a file
('<string>' is commonly used).
But it doesn't tell me much how to get this filename back from the AST node. Or how is this filename parameter is used. Is it just a stub?
It sets the co_filename attribute on the code object, which is used to display the filename in tracebacks. Besides that, it's not really significant what value you pass.
>>> c = compile('raise Exception("spam")', 'eggs', 'exec')
>>> eval(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "eggs", line 1, in <module>
Exception: spam
I'm working on a python script to thoroughly mutilate images, and to do so, I'm replacing every "g" in the file's text with an "h" (for now, it will likely change). Here's the beginning, and it's not working:
pathToFile = raw_input('File to corrupt (drag the file here): ')
x = open(pathToFile, 'r')
print x
After giving the path (dragging file into the terminal), this is the result:
File to corrupt (drag the file here): /Users/me/Desktop/file.jpeg
Traceback (most recent call last):
File "/Users/me/Desktop/corrupt.py", line 7, in <module>
x = open(pathToFile, 'r')
IOError: [Errno 2] No such file or directory: '/Users/me/Desktop/file.jpeg '
How can the file not exist if it's right there, and I'm using the exact filename?
Look closely: '/Users/me/Desktop/file.jpeg '. There's a space in your filename. open doesn't do any stripping.
>>> f = open('foo.txt', 'w')
>>> f.write('a')
>>> f.close()
>>> f = open('foo.txt ', 'r')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'foo.txt '