read and write files to different directories Python - python-2.7

I want my code to go into a sub directory, perform some operation and save the output in a file which is one step up, to the main dir.
Main directory ---> sub_directory
I would appreciate solutions which do not require "hardcoding" the path of the main
directory. Is there a way I can directly write my file output to the main dir without
doing a os.chdir() every iteration? Something like just giving the path of the file to read and write?
For eg:
# example
import os
for i in xrange(10):
code to read and operate on some file in this sub dir one by one (ten files)
# write output file to the previous directory
# without hardcoding the path
code to write files to main directory (ten files )

You probably want to check the directory the file is operating within or check the current working directory:
import os
cur_dir= os.getcwd()
top_dir = os.path.dirname(cur_dir)
# perform operations in current directory
# do some stuff in top directory

Assuming you start in the main directory, and you know the (relative) path to the subdirectories, just do
open(os.path.join(subdir, filename))
to access a path in a subdirectory without actually changing the current directory.

Related

Locating project-specifc configuration files from imported modules

Project structure:
/lib/modules/mod1.py
/mod2.py
/subdir1/subdir2/mod3.py
/configs/config.yaml
mod3.py imports mod2.py. mod2.py imports mod1.py. mod1.py loads configuration files that are at a relative path to mod2.py using os.getcwd().
The problem is that when mod3.py imports mod2.py, mod1.py attempts to load the config files from a path relative to mod3.py (i.e. /subdir1/subdir2/configs/config.yaml instead of /configs/config.yaml)--this, of course, doesn't work.
I believe understand why this isn't working (os.getcwd() get the path of the originally executed file).
How can I fix this so that mod1.py will use a path relative to mod2.py even when mod2.py is imported from mod3.py?
I haven't been able to find a built-in way to do this in Python, so what I ended up doing is this:
mod1.py:
configs_list = os.getcwd().split('/')
for x in configs_list:
# Check each directory in list, bottom up. 'pop()' list on
# each failure. Assign var and break loop when configs path is found.
if not os.path.exists('/'.join(configs_list) + '/configs'):
configs_list.pop()
else:
configs_path = '/'.join(configs_list) + '/configs'
break
configs_path is then used to prefix the specific configuration file name(s) in mod1.py. Since every call to mod1.py will occur from within a project's directory structure, and every project has only one configs directory, this should (and has so far) correctly identified the configs directory regardless of where in the project the given script is being run from.
I'm open to better or more Pythonic ways of doing this, if anyone has input.

urllib.urlretrieve creates file on disk

I do this:
thing = urllib.urlretrieve(url, "somefile.jpg")
It works, it gets the file, but it actually creates a file on the file system in the cwd. I write the file a little later to an appropriate path, but I don't want the file in the cwd at that time. What can I do?
Windows 10
If you want the file to go in a different directory, simply specify a path to where you want the file to go.
If you don't want the file to still be in the cwd after copying it, then delete the copy you don't want.
If you don't want to create a file at all, use something like urlopen.
There's a couple solutions 1. Change the cwd or 2. specify an alternate directory (as suggested by Scott Hunter), to do these:
1. Change your cwd (current working directory):
os.chdir("/Users/Desktop/SpecificDirectory/")
-now try your script.
OR
2. Specify an alternate directory in the download urllib command:
`thing = urllib.urlretrieve(url,"/Users/Desktop/SpecificDirectory/somefile.jpg")`

Opening a file in the current directory

I'm trying to load files, and previously I was using hardcoded file locations, (like "c:\location\file.txt") but now that a few friends are also using the file, I'd like to allow them to put the executable wherever they want.
my current code looks like:
ifstream myfile;
myfile.open("c:\\client\\settings.cfg");
I'm trying to change it so that the user puts their executable into whatever folder they want, and then they create a folder and put their settings file into it and the exe will load that with their settings.
ifstream myfile;
myfile.open("\\settings\\settings.cfg");
I have some basic error handling in place, and now the program always errors out saying that it can't find the file.
The file structure looks like this:
[ART]
asset.png
[SETTINGS]
settings.cfg
client.exe
This seems like a really simple thing to do, but I can't find any way to do it. Every example and tutorial about reading and writing to files deals only with files in the executable's directory, or hardcoded into c:\folder...
Could anyone point me to how I do this?
The search path for most systems starts with the current working directory and then to a PATH environment variable. So, all you need to do is specify the file/folder without the absolute path markings and it will use the path relative to the working directory:
ifstream myfile;
myfile.open("settings\\settings.cfg");
// ^^ Note the lack of \\ to start the file path
Paths beginning with \ are always relative to the current drive's root directory. If the current drive is C:, then \settings\settings.cfg means C:\settings\settings.cfg.
Note that you can use / in order to avoid escaping everything. So you can use: settings/settings.cfg. This will be relative to the user's current directory. Note however, that this doesn't necessarily correspond to the directory where the executable resides. If you need the directory of the executable, then you need to use a Windows API function to get it:
#include <Windows.h>
// ...
HMODULE module = GetModuleHandleW(NULL);
WCHAR path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
Now if you want to open settings/settings.cfg relative to the directory of the executable, create a path that starts with path and append /settings/settings.cfg to it.

C++ library path inclusion

i found C++ libraries could be included this way:
#include "..\example.h"
#include ".\another_example.h"
what is the dots used for?
They are to indicate the included file paths' are relative to the including file's actual path.
. points to the including file's actual directory
.. points to the including file's actual directories' parent diretory
Double dots stand for the parent directory of the currently entered path.
Single dot stands for the currently entered path on the left side of a dot and is used to show that you want a relative path.
A relative path is a path relative to the working directory of the
user or application, so the full absolute path will not have to be
given.
If you start your path with / (on *nix systems) or DRIVELETTER: (on Windows, e.g. D:) then the path is absolute. If you don't - the path is relative. If path is relative - it automatically prepends the directory of your file to the path entered.
Example:
"dir/././../dir/.." is the directory which contains the original file. The reductions are:
dir/././../dir/.. -> dir/./../dir/.. -> dir/../dir/.. -> /dir/.. -> . -> working directory. We removed ./ because it's alias to the current directory. We removed /dir/.. because we enter a directory with dir and get back with ..
One of the most often used features of ./ (but in the context of a shell, e.g. bash) - it forces to use a relative path instead of calling an executable program in the $PATH variable. For example if you type ls in terminal on *nix it will list the files in the working directory. If you type ./ls it will run executable with the name ls
in the current working directory and execute whatever this program does.
You can read more about path separators in this article on wikipedia
One dot is your current directory and two dots is your parent directory.
Two dots means one directory higher than the current one. For example, if you are in the directory C:\some\directory", "..\" would be "C:\some".
A single dot refers to the current directory. So using the previous example, ".\" would mean "C:\some\directory".
one dot . is for file's directory
2 dots .. are for file's parent directory.

Relative path problem for a deployed win32 application

I have written a c++ program and deployed it in say c:\my_app, and my executable's path is c:\my_app\my_app.exe. Say, my_app needs many files such as the_file.txt, which is located in c:\my_app\the_file.txt.
In my executable, I open the txt file as, xx.open("the_file.txt");
Moreover, I have associated my program with let's say .myp extension.
When I'm on Desktop, and want to open a file named example.myp, my program can not see the_file.txt. Because, it (somehow) assumes that it's currently working on Desktop.
Is there any easy way to handle this problem by changing shell command for open in HKEY_CLASSES_ROOT? The naive solution would be to change all file open operations with something like %my_app_location/the_file.txt". I don't want to do that.
Always use a full path name to open a file. In other words, don't open "foo.txt", open "c:\bar\foo.txt". To find the install directory of your EXE use GetModuleFileName(), passing NULL for the module handle.
These days you shouldn't add files to c:\my_app....
Instead use the ProgramData Folder and full paths.
Use SHGetSpecialFolderPathA with CSIDL_COMMON_APPDATA to get the ProgramData folder and the create your program directory and add your files.
You should set current directory for your app's folder with SetCurrentDirectory function. After that you can open file by name without full path