Python relative path problems - python

I am trying to create some helper functions that will give me a folder based on the relative paths:
def get_BASE_dir_path():
cur_dir = os.path.dirname(os.path.abspath(__file__))
BASE = os.path.abspath(os.path.join(cur_dir,"..",".."))
return BASE
def get_src_dir_path():
BASE = get_BASE_dir_path()
src_dir = os.path.abspath(os.path.join(BASE,"src"))
return src_dir
def get_lib_dir_path():
BASE = get_BASE_dir_path()
lib_dir = os.path.dirname(os.path.join(BASE,"src","lib"))
return lib_dir
def get_ffmpeg_dir_path():
BASE = get_BASE_dir_path()
ffmpeg_dir= os.path.dirname(os.path.join(BASE,"src","lib","ffmpeg"))
return ffmpeg_dir
But, somehow, I am not getting the right results when I print the functions:
Output:
C:\dev\project
C:\dev\project\src
C:\dev\project\src
C:\dev\project\src\lib
What did I miss?

The problem is here, in function get_lib_dir_path()
lib_dir = os.path.dirname(os.path.join(BASE,"src","lib"))
It should be:
lib_dir = os.path.join(BASE,"src","lib")
The same thing happens in get_ffmpeg_dir_path(). By calling dirname(), you chop off the last directory.

I guess it is because you are returning dirname instead of abspath for the last two values.

Related

File Not Found Error Django

Hello I'm new to django and I'm trying to make a web app. I have a running back end, but the problem is it's only running on cli and I have to turn it into a web app.
def testing(request):
ksize = 6
somsize= 10
csvname="input.csv"
testcap = "testing.pcap"
pl.csv5("chap/a",testcap)
tmparr=[]
for filename in os.listdir("chap"):
if filename.endswith(".csv"):
tmparr.append(filename)
continue
else:
continue
tmparr.sort()
visual_list = natsort.natsorted(tmparr)
csv = sl.opencsv(csvname)
norm = sl.normalize(csv)
weights = sl.som(norm,somsize)
label = sl.kmeans(ksize,weights)
#for x in range (2,21):
# label = sl.kmeans(x,weights)
# print("K is", x, "Score is ", label[1])
lblarr = np.reshape(label,(somsize,somsize))
#sl.dispcolor(lblarr)
classess = sl.cluster_coloring(weights,norm,csv)
classpercluster = sl.determine_cluster(classess,lblarr,ksize)
classpercent = sl.toperc(classpercluster)
print (classpercent)
#print(classpercluster)
for x in visual_list:
temp = ("chap/"+x)
tests = sl.opencsv(temp)
print(tests)
hits = sl.som_hits(weights, tests)
name = ("img/" + x + ".png")
sl.disp(lblarr,name,hits)
return render(request,'visualization/detail.html')
The system cannot find the path specified: 'chap', I'm not sure if I should put the chap folder inside the templates folder or in the app folder. Thank you in advance!
You're doing relative paths here it looks like. Change it to an absolute path.
dirpath = os.path.dirname(os.path.abspath(__file__))
chap_dirpath = os.path.join(dirpath, chap_dirpath)

Easy way to determine a type of file (regular file, directory, symlink etc.) by path in python

I wanted an easy way to determine a type of path so I googled alot and then I wrote this:
from stat import S_ISREG, S_ISDIR, S_ISLNK
from os import stat, lstat
from os.path import isfile, islink, isdir, lexists, exists
from enum import Enum, auto
class FileTypes(Enum):
FILE = auto()
LINK_TO_FILE = auto()
DIR = auto()
LINK_TO_DIR = auto()
BROKEN_LINK = auto()
NO_SUCH = auto()
UNDEFINED = auto()
def file_type(filename):
if lexists(filename):
if isfile(filename):
if islink(filename):
return FileTypes.LINK_TO_FILE
else:
return FileTypes.FILE
else:
if isdir(filename):
if islink(filename):
return FileTypes.LINK_TO_DIR
else:
return FileTypes.DIR
else:
if islink(filename):
return FileTypes.BROKEN_LINK
else:
return FileTypes.UNDEFINED
else:
return FileTypes.NO_SUCH
Then I googled more and wrote this:
def file_type2(filename):
if lexists(filename):
if exists(filename):
mode = stat(filename).st_mode
lmode = lstat(filename).st_mode # os.lstat doesn't follow symlinks
if S_ISREG(mode) and S_ISREG(lmode):
return FileTypes.FILE
elif S_ISREG(mode) and S_ISLNK(lmode):
return FileTypes.LINK_TO_FILE
elif S_ISDIR(mode) and S_ISDIR(lmode):
return FileTypes.DIR
elif S_ISDIR(mode) and S_ISLNK(lmode):
return FileTypes.LINK_TO_DIR
else:
return FileTypes.UNDEFINED
else:
return FileTypes.BROKEN_LINK
else:
return FileTypes.NO_SUCH
Both functions do what I want, but look kinda ugly and I think that I'm missing a simpler solution hiding in some cool python lib.
Question is: Is there a better way to do this?
You can try the pathlib module which has been in stdlib since Python 3.4 (for older pythons use pip install pathlib). It defines the Path class which contains methods for both checking types of files as well as resolving symlinks. Besides, it provides a pretty convenient API:
>>> from pathlib import Path
>>> path = Path("/etc/") / "passwd"
>>> path
PosixPath('/etc/passwd')
>>> path.is_file()
True
We can make it more consise with utilizing bitmasking inside enum:
Let's assume first value describes if file exists: 0 for existing and 1 for not existing, second one will be symlink: 1 for links and 0 for non-links, third for directory: 1 if it is directory and 0 if it is not, and the last for file in hte same menner.
So if we wanted to describe file that existsand is a symlink to file, we would use 0(exists)1(link)0(non-dir)1(file)
With using meaningful values we can now consisely chain those values together with results returned from python stat wrapper.
class FileTypes(Enum):
FILE = 1 #0001
LINK_TO_FILE = 5 #0101
DIR = 2 #0010
LINK_TO_DIR = 6 #0110
BROKEN_LINK = 4 #0100
NO_SUCH = 0 #1000
UNDEFINED = #0000
def file_type(filepath):
return FileTypes.NO_SUCH if lexists(filepath) else
Filetypes(int(
str(int(islink(filepath)))
+ str(int(isdir(filepath)))
+ str(int(isfile(filepath)))))
Obviously there is issue of some illegal states like if something would report that it is both directory and file, at that point this will raise exception, it can be modified for different behaviour, but raising exception seems perfectly valid.
Also I've used pretty ugly way of adding together this value, but this is for sake of readibility. You always could do ''.join(map(str,map(int,[islink(filepath),isdir(filepath),isfile(filepath)]))) or even shorter ways

Which paths does python ctypes module search for libraries on Mac OS?

Python documentation (I checked both 2.7 and 3.4) states that:
On OS X, find_library() tries several predefined naming schemes and paths to locate the library, and returns a full pathname if successful:
Then gives examples coming from two folders: /usr/lib and /System/Library. I suppose this is not full list, as I have experience with python finding library from /usr/local/lib. What is the full list of paths python ctypes find_library searches on Mac OS X?
The function definition from the source lists the possible paths:
if os.name == "posix" and sys.platform == "darwin":
from ctypes.macholib.dyld import dyld_find as _dyld_find
def find_library(name):
possible = ['lib%s.dylib' % name,
'%s.dylib' % name,
'%s.framework/%s' % (name, name)]
for name in possible:
try:
return _dyld_find(name)
except ValueError:
continue
return None
The relevant functions from macholib.dyld:
def dyld_env(env, var):
if env is None:
env = os.environ
rval = env.get(var)
if rval is None:
return []
return rval.split(':')
def dyld_image_suffix(env=None):
if env is None:
env = os.environ
return env.get('DYLD_IMAGE_SUFFIX')
def dyld_framework_path(env=None):
return dyld_env(env, 'DYLD_FRAMEWORK_PATH')
def dyld_library_path(env=None):
return dyld_env(env, 'DYLD_LIBRARY_PATH')
def dyld_fallback_framework_path(env=None):
return dyld_env(env, 'DYLD_FALLBACK_FRAMEWORK_PATH')
def dyld_fallback_library_path(env=None):
return dyld_env(env, 'DYLD_FALLBACK_LIBRARY_PATH')
def dyld_image_suffix_search(iterator, env=None):
"""For a potential path iterator, add DYLD_IMAGE_SUFFIX semantics"""
suffix = dyld_image_suffix(env)
if suffix is None:
return iterator
def _inject(iterator=iterator, suffix=suffix):
for path in iterator:
if path.endswith('.dylib'):
yield path[:-len('.dylib')] + suffix + '.dylib'
else:
yield path + suffix
yield path
return _inject()
def dyld_override_search(name, env=None):
# If DYLD_FRAMEWORK_PATH is set and this dylib_name is a
# framework name, use the first file that exists in the framework
# path if any. If there is none go on to search the DYLD_LIBRARY_PATH
# if any.
framework = framework_info(name)
if framework is not None:
for path in dyld_framework_path(env):
yield os.path.join(path, framework['name'])
# If DYLD_LIBRARY_PATH is set then use the first file that exists
# in the path. If none use the original name.
for path in dyld_library_path(env):
yield os.path.join(path, os.path.basename(name))
def dyld_executable_path_search(name, executable_path=None):
# If we haven't done any searching and found a library and the
# dylib_name starts with "#executable_path/" then construct the
# library name.
if name.startswith('#executable_path/') and executable_path is not None:
yield os.path.join(executable_path, name[len('#executable_path/'):])
def dyld_find(name, executable_path=None, env=None):
"""
Find a library or framework using dyld semantics
"""
for path in dyld_image_suffix_search(chain(
dyld_override_search(name, env),
dyld_executable_path_search(name, executable_path),
dyld_default_search(name, env),
), env):
if os.path.isfile(path):
return path
raise ValueError("dylib %s could not be found" % (name,))
def dyld_default_search(name, env=None):
yield name
framework = framework_info(name)
if framework is not None:
fallback_framework_path = dyld_fallback_framework_path(env)
for path in fallback_framework_path:
yield os.path.join(path, framework['name'])
fallback_library_path = dyld_fallback_library_path(env)
for path in fallback_library_path:
yield os.path.join(path, os.path.basename(name))
if framework is not None and not fallback_framework_path:
for path in DEFAULT_FRAMEWORK_FALLBACK:
yield os.path.join(path, framework['name'])
if not fallback_library_path:
for path in DEFAULT_LIBRARY_FALLBACK:
yield os.path.join(path, os.path.basename(name))
The defaults as per man dyld(1)
DEFAULT_FRAMEWORK_FALLBACK = [
os.path.expanduser("~/Library/Frameworks"),
"/Library/Frameworks",
"/Network/Library/Frameworks",
"/System/Library/Frameworks",
]
DEFAULT_LIBRARY_FALLBACK = [
os.path.expanduser("~/lib"),
"/usr/local/lib",
"/lib",
"/usr/lib",
]

Python: How to remove string from string

I have this snippet of code that looks like this:
server_directory = "/Users/storm/server"
def get_directory(self, username):
home = server_directory + "/" + username
typic = os.getcwd()
if typic == server_directory:
return "/"
elif typic == home:
return "~"
else:
return typic
And every-time I change the directory out of the two nice server directory and home directory of the user, it would look like /Users/storm/server/svr_user. How do I make it /svr_user2 instead of /Users/storm/server/svr_user, since I would like to emulate a home directory and a virtual "root" directory?
Although you can do a lot with string manipulation, a better way would be using os.path:
import os
src = '/Users/storm/server/svr_user'
dst = '/svr_user2'
a = '/Users/storm/server/svr_user/x/y/z'
os.path.join(dst, os.path.relpath(a, src))
returns
'/svr_user2/x/y/z'
The not so politically correct alternative of eumiro's answer would be:
import re
src = '/Users/storm/server/svr_user'
dst = '/svr_user2'
a = '/Users/storm/server/svr_user/x/y/z'
re.sub(src, dst, a, 1)
Which yields:
'/svr_user2/x/y/z'
Notice the 1 which means replace once.

Pythonic way to retrieve case sensitive path?

I was wondering if there was a faster way to implement a function that returns a case-sensitive path in python. One of the solutions I came up with works with both linux and windows, but requires that I iterate os.listdir, which can be slow.
This solution works fine for an application and context that does not need plenty of speed:
def correctPath(start, path):
'Returns a unix-type case-sensitive path, works in windows and linux'
start = unicode(start);
path = unicode(path);
b = '';
if path[-1] == '/':
path = path[:-1];
parts = path.split('\\');
d = start;
c = 0;
for p in parts:
listing = os.listdir(d);
_ = None;
for l in listing:
if p.lower() == l.lower():
if p != l:
c += 1;
d = os.path.join(d, l);
_ = os.path.join(b, l);
break;
if not _:
return None;
b = _;
return b, c; #(corrected path, number of corrections)
>>> correctPath('C:\\Windows', 'SYSTEM32\\CmD.EXe')
(u'System32\\cmd.exe', 2)
This however, will not be as fast when the context is gathering filenames from a large 50,000+ entry database.
One method would be to create a dict tree for each directory. Match the dict tree with the directory parts of the path, and if a key-miss occurs, perform an os.listdir to find and create a dict entry for the new directory and remove the unused parts or keep a variable counter as a way to assign a "lifetime" to each directory.
The following is a slight re-write of your own code with three modifications: checking if the filename is already correct before matching, processing the listing to lowercase before testing, using index to find the relevant 'true case' file.
def corrected_path(start, path):
'''Returns a unix-type case-sensitive path, works in windows and linux'''
start = unicode(start)
path = unicode(path)
corrected_path = ''
if path[-1] == '/':
path = path[:-1]
parts = path.split('\\')
cd = start
corrections_count = 0
for p in parts:
if not os.path.exists(os.path.join(cd,p)): # Check it's not correct already
listing = os.listdir(cd)
cip = p.lower()
cilisting = [l.lower() for l in listing]
if cip in cilisting:
l = listing[ cilisting.index(cip) ] # Get our real folder name
cd = os.path.join(cd, l)
corrected_path = os.path.join(corrected_path, l)
corrections_count += 1
else:
return False # Error, this path element isn't found
else:
cd = os.path.join(cd, p)
corrected_path = os.path.join(corrected_path, p)
return corrected_path, corrections_count
I'm not sure if this will be much faster, though there is a little less testing going on, plus the 'already-correct' catch at the beginning may help.
An extended version with case-insensitive caching to pull out the corrected path:
import os,re
def corrected_paths(start, pathlist):
''' This wrapper function takes a list of paths to correct vs. to allow caching '''
start = unicode(start)
pathlist = [unicode(path[:-1]) if path[-1] == '/' else unicode(path) for path in pathlist ]
# Use a dict as a cache, storing oldpath > newpath for first-pass replacement
# with path keys from incorrect to corrected paths
cache = dict()
corrected_path_list = []
corrections_count = 0
path_split = re.compile('(/+|\+)')
for path in pathlist:
cd = start
corrected_path = ''
parts = path_split.split(path)
# Pre-process against the cache
for n,p in enumerate(parts):
# We pass *parts to send through the contents of the list as a series of strings
uncorrected_path= os.path.join( cd, *parts[0:len(parts)-n] ).lower() # Walk backwards
if uncorrected_path in cache:
# Move up the basepath to the latest matched position
cd = os.path.join(cd, cache[uncorrected_path])
parts = parts[len(parts)-n:] # Retrieve the unmatched segment
break; # First hit, we exit since we're going backwards
# Fallback to walking, from the base path cd point
for n,p in enumerate(parts):
if not os.path.exists(os.path.join(cd,p)): # Check it's not correct already
#if p not in os.listdir(cd): # Alternative: The above does not work on Mac Os, returns case-insensitive path test
listing = os.listdir(cd)
cip = p.lower()
cilisting = [l.lower() for l in listing]
if cip in cilisting:
l = listing[ cilisting.index(cip) ] # Get our real folder name
# Store the path correction in the cache for next iteration
cache[ os.path.join(cd,p).lower() ] = os.path.join(cd, l)
cd = os.path.join(cd, l)
corrections_count += 1
else:
print "Error %s not in folder %s" % (cip, cilisting)
return False # Error, this path element isn't found
else:
cd = os.path.join(cd, p)
corrected_path_list.append(cd)
return corrected_path_list, corrections_count
On an example run for a set of paths, this reduces the number of listdirs considerably (this is obviously dependent on how alike your paths are):
corrected_paths('/Users/', ['mxF793/ScRiPtS/meTApaTH','mxF793/ScRiPtS/meTApaTH/metapAth/html','mxF793/ScRiPtS/meTApaTH/metapAth/html/css','mxF793/ScRiPts/PuBfig'])
([u'/Users/mxf793/Scripts/metapath', u'/Users/mxf793/Scripts/metapath/metapath/html', u'/Users/mxf793/Scripts/metapath/metapath/html/css', u'/Users/mxf793/Scripts/pubfig'], 14)
([u'/Users/mxf793/Scripts/metapath', u'/Users/mxf793/Scripts/metapath/metapath/html', u'/Users/mxf793/Scripts/metapath/metapath/html/css', u'/Users/mxf793/Scripts/pubfig'], 5)
On the way to this I realised the on Mac OSX Python returns path matches as if they are case-insensitive, so the test for existence always succeeds. In that case the listdir can be shifted up to replace it.

Categories

Resources