Specifying file name with mkstemp, file not found - python

I need to be able to create a temporary file with a specified file name and write data to it, then zip said file with filename up along with other files:
fd, path = tempfile.mkstemp(".bin", "filename", "~/path/to/working/directory/")
try:
with os.fdopen(fd, "wb") as tmp:
tmp.write(data)
with ZipFile("zip.zip", "w") as zip:
zip.write("filename")
zip.writestr("file2", file2_str)
zip.writestr("file3", file3_str)
# ...
finally:
os.remove(path)
I think I must be misunderstanding how mkstemp works, I get the error at the first line of code here:
FileNotFoundError: [Errno 2] No such file or directory: '~/path/to/working/directory/filenameq5st7dey.bin'
It looks like a bunch of garbage gets added to the file name before the suffix is put on the file. I've tried this without a suffix and I still get garbage at the end of the file name.
Aside from the garbage in the file name, why do I get a file not found error instead of having a temporary file created in my directory with that name (plus garbage)?

You supplied this argument:
"~/path/to/working/directory/"
Perfectly natural, it makes sense why you would supply it. But it is wrong. If you ls . you likely will not find a ~ directory.
What you were hoping for was expansion to ${HOME}, as the Bourne shell does. In python we must call this function:
os.path.expanduser("~/path/to/working/directory/")
Print the result it returns and you'll see why it's essential.
Some folks prefer to have pathlib do the work for them:
from pathlib import Path
Path("~/path/to/working/directory/").expanduser()

Related

Python Error:CSV File Error, Read/Print CSV file

I am getting this error when trying to print the contents of a CSV file in Python.
Traceback (most recent call last):
File "/Users/cassandracampbell/Library/Preferences/PyCharmCE2018.2/scratches/Player.py", line 5, in
with open('player.csv') as csvfile:
FileNotFoundError: [Errno 2] No such file or directory: 'player.csv'
Get the exact file path to the csv, if you are on a windows get the entire folder path and then the name, and then do:
with open(r'C:\users\path\players.csv') as csvfile:
If you're using a windows and the exact path, easiest to put the r before the path like I did because it is a literal which will allow the string to be interpreted and the path to be found.
You must put player.csv to the same location with your script Player.py
Example like your code, both files should be here: /Users/cassandracampbell/Library/Preferences/PyCharmCE2018.2/scratches/
Or you can put the specific directory of player.csv,
Ex:
with open("/Users/cassandracampbell/Library/Preferences/PyCharmCE2018.2/scratches/player.csv") as csvfile:
...
Check that you have the file in question in same directory as your .py file you're working on. If that doesn't work you might want to use the full path to the file:
with open ('/Users/cassandracampbell/Library/Preferences/PyCharmCE2018.2/scratches/player.CSV') as csvfile:
And you should try to check the name of the file too should be case sensitive otherwise, let's say you have Player.csv then don't try to open player.csv all lower case won't work!
Plus I don't know what you're trying to do with your CSV file, just print the raw content? You might like using pandas.

Python cannot see csv file

I went through couple answers on forum already but without any success.
I am using Linux mint, Python 3.6.0 and i am trying to open CSV in Python but then error occurs:
file = open("~/Desktop/xyz/city.csv", "rb")
FileNotFoundError: [Errno 2] No such file or directory: '~/Desktop/xyz/city.csv'
My code:
import csv
file = open("~/Desktop/xyz/city.csv", "rb")
reader =csv.reader(file)
I also tried to move the file to desktop as in some answers i found, instead of path i used "city.csv". Still doesn't work.
Completely new to Linux and just can't find why this isn't working.
Each reply appreciated!
You should'nt use '~' to specify the path of your directory but the full path instead. E.g. :
import csv
file = open("/home/user/Desktop/xyz/city.csv", "rb")
reader =csv.reader(file)
If you need to use the tilde, you should then use os.path.expanduser('~/Desktop/xyz/city.csv'). E. g. :
import csv
file = open(os.path.expanduser("~/Desktop/xyz/city.csv"), "rb")
reader =csv.reader(file)
The reason for that is that the "tilde expansion" is a user interface feature that is not recognized by the file system: http://www.gnu.org/software/bash/manual/bashref.html#Tilde-Expansion
Try using the full file path, something like this:
file = open("/home/[username]/Desktop/xyz/city.csv", "rb")
Usually ~ does not expand properly. I have found that when it is needed, put $HOME environment variable value into a python variable and then use join to attach it as a prefix to the file name relative position. This also allows you to move the file to a different location and create a function that will allow you to redefine the prefix.

Python - IOError: [Errno 13] Permission denied

Im trying to get a local directory from argv and iterate through the folder and print the contents of each file within. However i am getting a [Errno] 13 saying permission denied. Ive tried researching the problem but have come up empty handed.
#!/usr/bin/python
import os
import sys
path = open(sys.argv[1],'r') #'inputs/' path to working input dir
file_list = os.listdir(path) #create list of filenames in path dir
for fn in file_list:
file = open(path+'/'+fn) #open each file in dir for manipulation
for line in file:
print(line)
os.listdir(), as its name implies, returns a list of all occupants of the given directory, including both files and directories (and, if you're on Unix/Linux, other stuff like symlinks and devices and whatnot). You are then blindly trying to open() each item in the list and print() its contents. Unfortunately, open() only works on file-like objects, and specifically does not work on directories, hence Errno 13, Permission Denied.
An alternative is to use os.scandir(), which works a little bit differently. Instead of returning a flat list that you can read immediately, os.scandir() returns a generator which essentially gives you objects as you ask for them, instead of giving them all to you at once. In fact, the following code adapted from the docs is a good starting place for what you need:
for entry in os.scandir(path):
if entry.is_file():
print(entry.name)
os.scandir() is returning DirEntry objects. Simply use os.path.join() to create a full pathname out of the path argument you pass to os.listdir() in your original code, and entry.name from the code above, and then, using the with context manager, open() the file and display its contents:
for entry in os.scandir(path):
if entry.is_file():
with open(os.path.join(path, entry), "r") as f:
for line in f:
print(line)
One of the advantages of using with is that you don't have to remember to close the file handle that is assigned when you use something like this:
f = open("myfile.txt, "r")
# do stuff with f
...
f.close()
Otherwise, you have a dangling file handle that could potentially cause problems, depending on how many there are and what you've done with them. It's just a good practice to close() what you open(). With with, you don't have to worry about it - the file handle is closed as soon as you exit the block.

shutil.move deletes the file on windows when new name contains a colon (and an extension)

Try:
import os, shutil
wd = os.path.abspath(os.path.curdir)
newfile = os.path.join(wd, 'testfile')
print str(newfile)
with open(newfile, 'w') as f: f.write('Hello bugs')
shutil.move(newfile, os.path.join(wd, 'testfile:.txt')) # note the :
Now check the directory - newfile is deleted and no other file is created - Process finished with exit code 0.
If however you issue:
shutil.move(newfile, os.path.join(wd, 'testfile:')) # note no extension
it blows with:
Traceback (most recent call last):
File "C:/Users/MrD/.PyCharm40/config/scratches/scratch_3", line 9, in <module>
shutil.move(newfile, os.path.join(wd, 'testfile:'))
File "C:\_\Python27\lib\shutil.py", line 302, in move
copy2(src, real_dst)
File "C:\_\Python27\lib\shutil.py", line 130, in copy2
copyfile(src, dst)
File "C:\_\Python27\lib\shutil.py", line 83, in copyfile
with open(dst, 'wb') as fdst:
IOError: [Errno 22] invalid mode ('wb') or filename: 'C:\\Users\\MrD\\.PyCharm40\\config\\scratches\\testfile:'
as it should.
Is it a bug ?
Context: I was testing the behavior of my code when illegal filenames were given (: is illegal in windows filenames) when to my amazement my program deleted the original file (bad!) and created a zero size file with the attributes of the original (yes in my case the file was created, just empty) and filename the filename given up to the : - soo a filename like textfile:.jpg gave me a zero byte textfile. It took a lot of debugging - here is the little critter inside the Python27\lib\shutil.py copyfile() (the line that blows above and did not blow):
I don't know why in my case the file was created though while when running the script no.
This isn't a bug in Python's shutil or os modules, it's just a weirdness in Windows. Peter Wood's link in the comments discusses "Advanced Data Streams" -- a Windows filesystem mechanism that attaches a hidden file containing metadata to a regular, visible file. A key word there is attached; The hidden file is deleted if the file it is attached to is deleted.
It appears that a colon is used to separate the path of the regular file from the hidden file. For example, if in the command line you write:
> notepad foo
Then close notepad, and write
> notepad foo.txt:bar
Notepad will open the hidden file. Go ahead and write something in it, save, and close. Typing > dir and the command line will only show foo.txt, not foo.txt:bar.txt. But sure enough, if you write
> notepad foo.txt:bar.txt
the file you just edited will appear, and your changes will be intact.
So what is happening with your Python code? The documentation for shutil.move says:
src is copied (using shutil.copy2()) to dst and then removed.
So when you move testfile to testfile:.txt, Python first copies testfile to the hidden testfile:.txt. But then it removes testfile, and by doing so removes the hidden testfile:.txt. Therefore it appears to you that the original file has been deleted, and no new file has been created.
The following snippet of code might make this clearer (I've saved it as demo.py, and I'm running it in the same, other-wise empty directory):
import os, shutil
with open('test', 'w') as f:
f.write('Hello bugs')
shutil.copy2('test', 'test:foo.txt')
with open('test:foo.txt') as f:
print(f.read())
print 'test: exists? ', os.path.exists('test')
print 'test:foo.txt exists? ', os.path.exists('test:foo.txt')
print os.listdir('.')
print('removing...')
os.remove('test')
print 'test: exists? ', os.path.exists('test')
print 'test:foo.txt exists? ', os.path.exists('test:foo.txt')
print os.listdir('.')
This prints:
Hello bugs
test exists? True
test:foo.txt exists? True
['demo.py', 'test']
removing...
test: exists? False
test:foo.txt exists? False
['demo.py']
This shows that we can create a normal file, write to it, and copy that normal file to its hidden stream, open, and read it just fine, and the result is as expected. Then we see that os.path.exists shows that both test and it's hidden attachment test:foo.txt exist, even though os.listdir only shows test. Then we delete test and we see that test:foo.txt no longer exists as well.
Lastly, you can't create a hidden data stream without a name, therefore test: is an invalid path. Python correctly throws an exception in this case.
So the Python code is actually functioning as it should under Windows -- "Alternate Data Streams" are just such a little-known "feature" that this behavior is surprising.

creating multiple directories

I am trying to create multiple subdirectories and move files into those subdirectories, name the subdirectory the number of which loop it is on, this is what i have:
for x in range(1,20):
os.makedirs('{}/'.format(replace)+str(x)+'/')
shutil.move(filename,'{}/'.format(replace)+str(x)+'/')
shutil.move(filename1,'{}/'.format(replace)+str(x)+'/')
I am getting this error:
File "testdraft.py", line 285, in findReplace
shutil.move(f, '{}/'.format(replace)+str(x)+'/')
File "/usr/lib/python2.7/shutil.py", line 284, in move
if _samefile(src, dst):
File "/usr/lib/python2.7/shutil.py", line 58, in _samefile
return os.path.samefile(src, dst)
File "/usr/lib/python2.7/posixpath.py", line 162, in samefile
s1 = os.stat(f1)
TypeError: coercing to Unicode: need string or buffer, file found
thanks for any help
Presumably your f is a file object, not a filename.
You didn't actually show us any code that calls shutil.move with an f; you instead showed us code that calls it with something named filename1. But it doesn't matter what the name of the variable is; if what it holds if a file object that you got back from, e.g., the open function, you can't use it with move.
Hopefully, your real code is as simple as something like:
with open(out_path, 'w') as f:
write_data(f)
shutil.move(f, '{}/'.format(replace)+str(x)+'/')
Then you just want to change the f in the last line to out_path and you're done.
It looks like your filename or filename1 variables are not actually file names, but file objects. (This is what that "file found" at the end of your error is trying to tell you.)
Additionally, you may want to consider not making the directories first:
shutil.move(src, dst):
The destination directory must not already exist. If the destination
already exists but is not a directory, it may be overwritten depending
on os.rename() semantics.

Categories

Resources