How to load resources file without giving entire path in Python - python

I want to read the properties file in Python without giving the entire path. Because if my code is deployed somewhere else then my package would fail if I pass the hardcore value. So below is my code to read the properties file by giving the entire path:
import configparser
config = configparser.RawConfigParser()
config.read('C:\\Users\\s\\IdeaProjects\\PysparkETL\\src\\main\\resources\\configs.properties')
dbname = config['DB']['dbname']
username=config['DB']['user']
password=config['DB']['password']
table=config['DB']['tablename']
driver=config['DB']['driver']
print(dbname)
and below is my configs.properties file:
[DB]
dbname=ourdb
user=root
password=root
tablename=loadtable
driver=com.mysql.cj.jdbc.Driver
I tried different ways like ConfigParser instead of RawConfigParser but didn't work. Is there any way to load files from the classpath?
Also, I tried different ways from this link but it didn't help. All I need is a path to pass it to config.read method but it should not be hardcoded as I did it in the code.
Below is my project structure:
Also, as suggested I tried below code and passed the URL to the config.read method but it's not working.
props = os.path.join(
os.path.dirname("resources"), # folder where the python file is
'src/main/resources/configs.properties'
)
config.read(props)
I get below error:
raise KeyError(key)
KeyError: 'DB'

if the file will always be in the same place relative to your python file, you can do the following:
props = os.path.join(
os.path.dirname(__name__), # folder where the python file is
'relative/path/to/configs.properties'
)

Related

Can't find the file from views.py

I am stuck with a really weird problem.
I have a file called: "test.txt".
It is in the same directory with views.py. But I can't read it... FileNotFoundError.
But if I create read_file.py in the same directory with views.py and test.txt, it works absolutely fine.
What is wrong with views? Is this some sort of restriction by Django?
This code works on read_file, doesn't work on views.py:
fkey = open("test.txt", "rb")
key = fkey.read()
I think the problem may be relative vs absolute file handling. Using the following Python snippet, you can work out where the interpreter's current working directory is:
import os
print(os.getcwd())
You should notice it's not in the same directory as the views.py, as views.py is likely being invoked/called from another module. You may choose to change all your open calls to include the whole path to these files, or use an implementation like this:
import os
# This function can be used as a replacement for `open`
# which will allow you to access files from the file.
def open_relative(path, flag="r"):
# This builds the relative path by joining the current directory
# plus the current filename being executed.
relative_path = os.path.join(os.path.dirname(__file__), path)
return open(relative_path, flag) # return file handler
Then, this should work:
fkey = open_relative("test.txt", "rb")
key = fkey.read()
Hope this helps!

Need help for relative paths imports

Please find attached my files structure:
My micro_service.py file requires the app_config.ini on startup. Here is how I call the .ini file from it.
app_config = ConfigParser()
app_config.read("./app_config.ini")
CONFIG_SECTION_APP = app_config.sections()[0]
My test_micro_service.py needs to import all the functions in the micro_service.py file to test them since it's a unit tests file.
This is how I used to import my functions until now that I added the .ini file procedure:
root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(root)
from micro_service import micro_service
The issue I'm facing is that due to changing the working directory using the sys.path command, inside the test_micro_service.py file, when importing my .ini file, the working directory being different causes "./app_config.ini" not to be found (which makes sense) and so it causes my tests to fail because CONFIG_SECTION_APP = []
I did read plenty of stuff on the internet but I would like to know what are the simplest/cleanest ways do it ?
Console output:
================================================================================================================== ERRORS ==================================================================================================================
____________________________________________________________________________________________ ERROR collecting unit_tests/test_micro_service.py _____________________________________________________________________________________________
unit_tests\test_micro_service.py:4: in <module>
from micro_service import micro_service
micro_service\micro_service.py:16: in <module>
CONFIG_SECTION_APP = app_config.sections()[0]
E IndexError: list index out of range
Content of the ini file:
; Configuration file used by micro_service.py
[APP]
DICT_VERSION_GENERAL = 1.0
DICT_VERSION_PERSONAL = 1.0
I found the solution to my problem:
This is how I should call my file inside the micro_service.py
app_config.read(os.path.dirname(os.path.realpath(__file__)) + "\\app_config.ini")
You can use pathlib.Path :
# in micro_service.py
from pathlib import Path
app_config = ConfigParser()
path = Path().resolve() / "app_config.ini"
app_config.read(path)
CONFIG_SECTION_APP = app_config.sections()[0]

OSError: cannot open shared object file: No such file or directory even though file is in the folder

I've been fighting with this for quite some time now. I'm trying to install Yaafe for audio feature extraction. I follow instructions here: https://github.com/Yaafe/Yaafe
Everything installs up nicely, but when I try to run the test file "frames.py" I get following error:
File "frames.py", line 6, in <module>
from yaafelib import FeaturePlan, Engine, AudioFileProcessor
File "/usr/local/lib/python2.7/dist-packages/yaafelib/__init__.py", line 36, in <module>
from yaafelib.core import (loadComponentLibrary,
File "/usr/local/lib/python2.7/dist-packages/yaafelib/core.py", line 35, in <module>
yaafecore = cdll.LoadLibrary('libyaafe-python.so')
File "/usr/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
return self._dlltype(name)
File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
self._handle = _dlopen(self._name, mode)
OSError: libyaafe-python.so: cannot open shared object file: No such file or directory
I have included the lib directory to LD_LIBRARY_PATH with following command:
export LD_LIBRARY_PATH=/usr/local/lib
And indeed when I echo the LIBRARY_PATH it is there. Also when I check the /usr/local/lib it has following contents:
libyaafe-components.so libyaafe-io.so python2.7
libyaafe-components.so.0 libyaafe-io.so.0 python3.4
libyaafe-components.so.0.70.0 libyaafe-io.so.0.70.0 site_ruby
libyaafe-core.so libyaafe-python.so yaafe
libyaafe-core.so.0 libyaafe-python.so.0
libyaafe-core.so.0.70.0 libyaafe-python.so.0.70.0
So shouldn't everything be okay? I don't understand what is the problem. I've followed instructions to the point.
Change your code so that you print os.environ right before that exception occurs. That way you will see whether the Python process has the correct environment set or not. The other obvious thing to check are whether your Python process has sufficient permission to open and read libyaafe-python.so. Note that sudo by default limits the environment of the invoked command, for security reasons (see here, for instance).
I know this post is old, but if you cannot modify (or do not want to modify) LD_LIBRARY_PATH and you still need a way to load the shared object into memory in Python, then you can use this general approach.
import ctypes
ctypes.CDLL('/usr/local/lib/library.version.so', mode=ctypes.RTLD_GLOBAL)
For you, the call might look like:
import ctypes
ctypes.CDLL('/usr/local/lib/libyaafe-python.so', mode=ctypes.RTLD_GLOBAL)
And if you don't know the path beforehand, I've put together the following function that can recursively search a set of library paths for a specified library name (and version). Hope this helps!
# Given a library name, try to locate the library and load it in
# global mode as a CDLL so that it is accessible to all code.
def load_library(libname, version=None, paths=("/usr/lib","/usr/local/lib",),
extensions=(".so",), prefixes=("","lib",),
recursive=True):
import os, ctypes
# This code will find all possible matches for the library,
# and pick the first lexicographically.
versions = set()
for directory in paths:
# Enumerate all files at that path (depending on "resursive" option).
if recursive:
file_paths = sum((
[os.path.join(dirpath, f) for f in filenames]
for (dirpath, dirnames, filenames) in os.walk(directory)
), [])
else:
file_paths = [
os.path.join(directory,f) for f in os.listdir(directory)
if not os.path.isdir(f)
]
# Iterate over the files looking for the specified library.
for path in file_paths:
filename = os.path.basename(path)
# Verify the file extension is allowed.
ext = filename[len(filename)-filename[::-1].find('.')-1:]
# Examples of the value for 'ext' given a 'filename':
# "foo.bar" -> ".bar", "foobar" -> ""
if (ext not in extensions): continue
# Check that the library name is in file name.
if (libname not in filename): continue
# Check that the version is in the name (if it is specified).
file_version = ".".join(filename.split('.')[1:-1])
if ((version is not None) and (version != file_version)): continue
# Extract the file name and check for matches against prefixes.
name = filename[:(filename+'.').find('.')]
for p in prefixes:
if (p+libname == name): break
else: continue
# Now this filename matches the required:
# name preceding the first ".",
# file extension including last ".",
# version between first and last "." if that was specified,
# and it exists in one of the provided paths.
versions.add(path)
# Uncomment the following line to see the considered libraries.
# print([path, filename, name, file_version, ext, os.path.islink(path)])
# Raise an error if no versions could be found.
if (len(versions) == 0):
raise(FileNotFoundError(f"No library file found for '{libname}'{'' if version is None else ' version '+version}."))
# Get the library path as the first element of the set of discovered versions.
library_path = sorted(versions)[0]
# Load the library globally (so it is accessible to later codes) and return its path.
ctypes.CDLL(library_path, mode=ctypes.RTLD_GLOBAL)
return library_path
And for your specific example the call to the function would look like:
load_library("yaafe-python")
As long as you called this before importing whatever module was failing to load, everything should work.
WARNINGS
This is written for POSIX systems (Ubuntu, macOS, ...)
This loads the library into the global C namespace, so I am not sure how it will handle duplicate declarations if something already exists and it might cause unexpected downstream consequences if a loaded library is overwritten.

How to get the path of the posted file in Python

I am getting a file posting from a file:
file = request.post['ufile']
I want to get the path. How can I get it?
You have to use the request.FILES dictionary.
Check out the official documentation about the UploadedFile object, you can use the UploadedFile.temporary_file_path attribute, but beware that only files uploaded to disk expose it (that is, normally, when using the TemporaryFileUploadHandler uploads handler).
upload = request.FILES['ufile']
path = upload.temporary_file_path
In the normal case, though, you would like to use the file handler directly:
upload = request.FILES['ufile']
content = upload.read() # For small files
# ... or ...
for chunk in upload.chunks():
do_somthing_with_chunk(chunk) # For bigger files
You should use request.FILES['ufile'].file.name
you will get like this /var/folders/v7/1dtcydw51_s1ydkmypx1fggh0000gn/T/tmpKGp4mX.upload
and use file.name, your upload file have to bigger than 2.5M.
if you want to change this , see File Upload Settings
We cannot get the file path from the post request, only the filename, because flask doesn't has the file system access. If you need to get the file and perform some operations on it then you can try creating a temp directory save the file there, you can also get the path.
import tempfile
import shutil
dirpath = tempfile.mkdtemp()
# perform some operations if needed
shutil.rmtree(dirpath) # remove the temp directory

py2exe access 'other_resources'

So with py2exe you can add additional data inside the library zip file, now I was wondering, how do you access this data, do you need to read it out from the zipfile or can you just access it like any other file ? or perhaps there's another way to access it.
I personally never used the zipfile. Instead, I pass the data files my program used in the setup method and use the bundle_files option (as described at the bottom of this page). For instance, the program I create using this call
setup(name = "Urban Planning",
windows = [{'script': "main.py", "dest_base": "Urban_Planning"}],
options = opts, # Dictionary of options
zipfile = None, # Don't create zip file
data_files = Mydata_files) # Add list of data files to folder
also has a piece before it where a config file and some images for the user interface are added like this
Mydata_files = [] # List of data files to include
# Get the images from the [script root]/ui/images/ folder
for files in os.listdir(sys.path[0] + '/ui/images/'):
f1 = sys.path[0] + '/ui/images/' + files
if os.path.isfile(f1): # This will skip directories
f2 = 'ui/images', [f1]
Mydata_files.append(f2)
# Get the config file from the [script root]/Configs folder
Mydata_files.append(('Configs', [sys.path[0] + '/Configs/defaults.cfg']))
This way I can call my config file just like I would while running the script using idle or command prompt and my UI images display correctly.

Categories