Is there a way to get the directory path of the calling file in python - python-3.x

I'm currently using the code below to find a configuration file in the current project
kRootPath = os.path.dirname(os.path.abspath(__file__))
kConfRootPath = os.path.join(kRootPath, '..', 'ConfigFiles' )
This currently works for my original project. I now have multiple projects that want to use this include file. I need the location of the file that called the include instead of the include itself.
Details:
Project 1
Config
1a.cfg
1b.cfg
Code
code1a.py
code1b.py
theInclude.py
Project 2
Config
2a.cfg
2b.cfg
Code
code2a.py
code2b.py
If all code files include theInclude.py then the include file should return the configure Path for:
project 1 if included from code1a.py or code1b.py
project 2 if included from code2a.py or code2b.py

Related

how to avoid mixture of \ and / in file paths when joining paths in Docker containerized Python code

As far as I'm aware I'm using best practices to define paths (using raw strings) and how I go about joining them (using os.path.join()), e.g.
import os
fdir = r'C:\Code\...\samples'
fpath = os.path.join(fdir, 'fname.ext')
and doing so has not caused me any problems when running my code within a Python or command shell. If I print fpath to the console I get consistent use of \s in the path:
C:\Code...\samples\fname.ext
But when I run a Docker containerized version of the code and run the image I get the error:
FileNotFoundError: [Errno 2] No such file or directory:
'C:\Code\...\samples/fname.ext'
I don't understand why os.path.join() has used a / to join fdir and fname.ext when the rest of the path included \\. It doesn't do this when I run the code outside of the container.
I have tried using os.path.normpath():
fpath = os.path.join(fdir, 'fname.ext')
fpath = os.path.normpath(fpath)
as discussed here, and os.sep.join():
fpath = os.sep.join([fdir, 'fname.ext'])
as covered here, and Path().joinpath():
from pathlib import Path
fpath = Path(fdir).joinpath('fname.ext')
as well as Path() / 'path_to_add':
fpath = Path(fdir) / 'fname.ext'
as discussed here, but in every case I end up with the same result using os.path.join().
Can someone please help me to understand what is going on and how to create consistent paths that will work whether I run the code in Python in a Windows environment, or in a Docker container?
Update Nov. 16:
In trying to keep my question brief I think I've left out details that are crucial. Apologies to those who have kindly taken the time to offer suggestions based on my incomplete description of the problem.
My code needs to import/export files from/to directories that are defined within a user-specified configuration file.
So the configuration file has a section of code where the user defines variables and paths, e.g.
samplesDir = r"path-to-samples-directory"
The variables are stored in a dictionary of dictionaris and stored as a .json.
At the start of the code the user defines the key that selects the dictionary of interest so that at various parts in my code when a file needs to be imported/exported, the paths are at hand.
So back to my example, samplesDir is stored in the configuration dictionary, cfgDict, so all I need to do is append the file name:
sampleFpath = os.path.join(sampleDir, sampleFname)
and sampleFname is determined based on other variables.
Because of the dynamic nature of the variables (including directory paths and file paths), I think it rules out the use of static path defined in a .yml with Docker Compose.
Update Nov. 18:
It may help to include a few more details and some screenshots.
The above screenshot shows the file and folder structure of the src directory containing the source code, the main app.py script for command-line use, the Dockerfile, etc.
The configs folder contains JSON files that includes variables, paths to directories and files. The user can create configuration files either by copying an existing one and modifying the entries, or configuration files can be generated by calling config.py.
Within config.py I have pre-set variables and paths, so that the directory path to the configuration files (configs), sample files (sample_DROs) and others (e.g. fiducials) are all within src.
I don't anticipate any reason why the user would want to store the config files anywhere else, nor do I expect them to want to use different sample files (or move them elsewhere). However, they will undoubtedly create their own fiducials and may decide not to store them in the fiducials directory (i.e. somewhere not within the src directory).
Likewise I have pre-set the download directory (based on the parameters stored within the configuration files, files are fetched from a server and downloaded) to be the default Downloads directory:
rootDownloadDir = os.path.join(Path.home(), "Downloads", "xnat_downloads")
Those files are later imported, processed, and the outputs are (by default) exported into sub-directories within rootDownloadDir.
Within Dockerfile I set the working directory of the container to be that of the source code and copy all of the contents of src (with the exception of some directories defined in .dockerignore):
WORKDIR C:/Code/WP1.3_multiple_modalities/src
...
COPY . .
so that the structure of the container mimics that of WORKDIR:
Hence I have allowed for flexibility in import/export directories, and they are by default a combination of paths within and outside of the src directory. And so, the code executed within the container will need to access files both within and outside of src.
That said, I don't know what rootDownloadDir will look like when os.path.join(Path.home(), "Downloads", "xnat_downloads") is run within the container.
This has got me thinking - Is it bad practice to set the download directory outside of src?
Returning to the original error:
the sample file is in the container:
From the actual behavior I can suppose that the container is based on Unix-like image. Path separator is / in such systems.
To build an environment-independent path which works inside and outside of the container you need the following steps:
Mounting of host folder to container directory.
Environment variable inside and outside the container.
I can show an example of how this is achievable via docker-compose tool and its configuration file docker-compose.yml:
# docker-compose.yml file
version: '3'
services:
<service_name>: # your service name here
image: <image_name> # name of image your container is built on
environment:
- SAMPLES_PATH=/samples
volumes:
- C:\Code\somepath\samples:/samples
In your python code you can use the following structure:
import os
fdir = os.getenv('SAMPLES_PATH', r'C:\Code\...\samples')
fpath = os.path.join(fdir, 'fname.ext')

define path to SConstruct root

My folder structure is:
\gitclone\SConstruct
\gitclone\level1\level2\SConscript.3dn
Now in SConscript.3dn I am creating empty folder: e.Execute(Mkdir('#/testDir'))
How to define the file path to create the folder in \gitclone\ (where root SConstruct file is)? I was reading manual, but somehow I can not manage it.
I have found solution here, so my code is:
e['SCONS_ROOT'] = Dir('#')
e.Execute(Mkdir('${SCONS_ROOT.abspath}/win_b64/code/bin/testDir'))

Referencing a directory outside of current directory. "Modules does not exist in the module map." in node/react-native

I have the following directory structure
Apps
|--ComponentLibrary
|----package.json
|--MyProject1
|----package.json
|--MyProject2
|----package.json
I want to be able to use components from ComponentLibrary in MyProject1 like:
MyProject1/App.js
import {Button} from 'ComponentLibrary/components/button';
Is there a way I can alias ComponentLibrary in MyProject1? I imagine there's some flag I can add in package.json
Currently I get the following expected error
Modules does not exist in the module map

AWS Lambda access denied to a module in subfolder

I have this Nodejs lambda function where some files are in a subfolder, like this:
- index.js
- connectors/
- affil.js
I have a Cannot find module error when trying to require the affil.js file. Trying to read it with fs.readFile returns an access denied error.
When I move the file to the root folder, it is accessible. Is there a requirement that Lambda functions files must all be at the root directory? How can I fix that?
Mostly it is because of the way zipping the files making the problem. Instead of zipping the root folder you have to select all files and zip it like below,
Please upload all files and subfolders like below. Please include node_modules folder as well in the zip.
As pointed by #Vijayanath Viswanathan, the issue is with how the zip file is created rather than Lambda.
I used to feed gulp-zip with this:
var src = gulp.src('src/**/*')
The correct way is to prevent folders from being included:
var src = gulp.src('src/**/*.js')
or (if you need to include file with other file extensions)
var src = gulp.src('src/**/*', {nodir: true})

Require file somewhere in the directory node.js

I have a file that is required in many other files, that are on different folders, inside the main directory.
Is there a way to just require the filename without having to write the relative path, or the absolute path? Like require('the_file'). And without having to go to npm and install it?
Create a folder inside your main directory , put the_file.js inside and set the NODE_PATH variable to this folder.
Example :
Let's say you create a ./libs folder within your main directory, you can just use :
export NODE_PATH = /.../main/lib
after that, you can require any module inside this directory using just :
var thefile = require('the_file')
To not have to do that every time, you'd have to add the variable to your .bashrc (assuming you're running a Unix system).
Or you can set a global variable inside your app.js file and store the path of your 'the_file' in it like so :
global.rootPath = __dirname;
Then you can require from any of your files using :
var thefile = require(rootPath+'/the_file')
These are the most convenient methods for me, short of creating a private npm, but there are a few other alternatives that I discovered when looking up an answer to your question, have a look here : https://gist.github.com/branneman/8048520

Resources