I'm trying to copy files from source to destination. The file is there in the source location. The exception is raised on the destination file. Specifically, the try: os.close(fout)
line. The traceback.print_exc()
is UnboundLocalError: local variable 'fout' referenced before assignment
.
fout
is assigned prior to that line, fout = os.open(dst, WRITE_FLAGS, stat.st_mode)
. It appears to only throw the exception on certain files. I've been away from python for a little bit now. Not really understanding why the exception is being thrown. I believe fout
is not opening/creating the file. But why no exception at fout = os.open(dst, WRITE_FLAGS, stat.st_mode)
or during the write os.write(fout, x)
. Any help to point me in the write direction is greatly appreciated.
Original copyfile code is from this thread How to Copy Files Fast.
import os
import traceback
class CTError(Exception):
def __init__(self, errors):
self.errors = errors
try:
O_BINARY = os.O_BINARY
except:
O_BINARY = 0
READ_FLAGS = os.O_RDONLY | O_BINARY
WRITE_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | O_BINARY
BUFFER_SIZE = 128*1024
def copyfile(src, dst):
try:
fin = os.open(src, READ_FLAGS)
stat = os.fstat(fin)
fout = os.open(dst, WRITE_FLAGS, stat.st_mode)
for x in iter(lambda: os.read(fin, BUFFER_SIZE), ""):
os.write(fout, x)
finally:
try: os.close(fin)
except:
#fin2 = open("C:\\Users\\testUser\\ScriptErrLogs\\saveErrors.txt", 'a ')
#fin2.write(traceback.print_exc())
#fin2.close()
pass
try: os.close(fout)
except:
fin2 = open("C:\\Users\\testUser\\ScriptErrLogs\\saveErrors.txt", 'a ')
e = str(traceback.print_exc())
fin2.write(e)
fin2.close()
print os.path.isfile(src)
print os.path.isfile(dst)
pass
DEBUG = 1
f = open('C:\\Users\\testUser\\Scripts\\Python\\testImport.csv','r')
lines = f.readlines()
for line in lines:
temp = line.split('\\')
tempFileName = line[0:-1]
tempPath = 'C:\\Users\\testUser\\testSaveLocation\\testSave'
# DEBUG prints
if DEBUG == 0:
print '#### LINE ####'
print line
print '#### FILENAME ####'
print tempFileName
# Discard the first 3 elements to create the new location path
for entry in temp[3:]:
tempPath = tempPath '\\' entry
# DEBUG prints
if DEBUG == 0:
print '#### TEMPPATH ####'
print tempPath
# Check path exists
pathExists = os.path.exists(tempPath)
# Create directory structure
if not pathExists and not '.pdf' in entry:
try:
os.mkdir(tempPath)
except OSError as error:
print error
# Copy file to new location
if '.pdf' in entry:
try:
copyfile(line[:-1],tempPath[:-1])
except OSError as error:
print error
CodePudding user response:
Looks to me like fout is being assigned inside a try
block, and used inside a finally
block. Maybe your code is excepting out before fout gets assigned.
One easy fix, perhaps: set fout = None
before the try
, and only perform the close if fout is not None (and to be safe, you may want to protect fin the same way).
To debug why you're excepting out early, you can catch the exception and print it out:
...
def copyfile(src, dst):
fin = None
fout = None
try:
fin = os.open(src, READ_FLAGS)
stat = os.fstat(fin)
fout = os.open(dst, WRITE_FLAGS, stat.st_mode)
for x in iter(lambda: os.read(fin, BUFFER_SIZE), ""):
os.write(fout, x)
except Exception as e:
print e
finally:
...
Once you figure out what's going on, you should be able to handle the error case in the try block, or before you perform the excepting operation.
CodePudding user response:
Turns out this is not a FileNotFoundError or a UnboundLocalError issue, its a path length issue.
fin
opens without issue but when assigning fout
, in my case, the path length is too long. Manually typing the statement fails at the original fout
assignment. I'm trying to preserve the path of the original file, just stored in a different root folder. It occurred to me that it maybe a path length issue, looking at the original path. I shortened the path to the destination and the copy worked.
Prepending \\\\?\\
to tempPath
resolved the issue. All files copied without issue. For local drives, \\\\?\\c:\\
resolved the issue. For network shares, \\\\?\\server\\share
would resolve the issue for me as well.