I am creating a small application in Python that needs to read a configuration file.
I intend to save this file in a folder in /etc on Linux, but I would like my application to run on other operating systems.
The question is: Is there some kind of constant, variable, package, etc. that can tell me the path to the most sensible settings folder on an OS?
Maybe it is better to locate your configuration file(s) in a folder related to your actual module/application? Determine the location of your module might not be straight forward, but this thread should help.
One tool which maybe useful, configparser, has a function which actually looks for configuration files in some standard locations: RawConfigParser.read(filenames)
As far as I know there is no builtin constant for this, but it seems fairly easy to do it manually.
You could use sys.platform or os.name to get the OS, and then set the config folder according to this.
os_name = sys.platform
cfg_folder = {'linux2': '/etc', 'win32': 'folder', ...}[os_name]
You might want to check http://docs.python.org/library/os.html#os-file-dir .
After getting the root path you are able to select specific paths depending on the working OS.
Related
I have a python program that I've written that requires a specific database that is located in a folder on my computer directory.
Currently my program initializes the database in the same location as where the python script is found, and I thought this is the best way to do it so that the database stays 'static' relative to the script.
My question is, is there a different way of doing this? Perhaps some kind of best practice? Also, what exactly is this concept called?
This is my first time to write a program for other people to use and I'm a bit nervous that it might break somewhere.
I would use the user's home folder and use the os.path module. Let's say you have a program named myapp and a database called db.sqlite.
import os.path
path = os.path.expanduser('~/.myapp/db.sqlite')
path would then be expanded to /home/user/.myapp/db.sqlite on a UNIX-based system (and similar for Mac) and C:\Users\user\Application Data\Roaming.myapp\db.sqlite (or something similar, not on a windows machine) on a Windows machine.
I have a python program that must work on Windows and Linux. There are some configuration options I normally store in a file, in a subdirectory of the program's directory.
For Windows, I converted it to exe and created an Installer for it. And now I have the problem of dealing with the config file.
What is the best place to save the configuration file? I have read that for Windows os.environ['APPDATA']+'myAppName' is the path that must be used. Is it correct? Is it standard? Will it work in all versions of Windows at least from XP (and at least in English and Spanish)?
PD: I am not interested in using ConfigParser. Config file is in my own format and I have working code for reading/writing from it.
Storing settings in the user directory is usually a good idea.
These days, you should probably use something like the appdirs library to find a good path to store your configuration in.
Under most Unices, just store a (preferably dot-prefixed) file in the home directory. Under OS X, you'd want to create a directory for your application in the user's Library folder, and store your files there. Under Windows, APPDATA is a good place to build a directory in for your application. It should work on all Windows localizations, and it looks like it was also available in Windows XP.
platformdirs
There is a better solution now ... better than speculating about what is best on each platform, better than environment variables which may or may not be defined, and even better than appdirs: platformdirs (GitHub, PyPI Snyk).
import platformdirs
appname = 'OurGreatApp'
print(f"User config files should be stored in {platformdirs.user_config_dir(appname)}")
On Linux, it is common to store the configuration file in the users home directory, for instance ~/.myprogramrc. On windows Vista and up, users have a home directory as well (/Users/username) and a would recommend storing your settings there in a subfolder (/Users/useranem/myprogram). Storing the settings in the application folder will generate UAC warnings.
On Windows XP, users do not have a home folder. Some programs make the choice of putting configuration in the 'My Documents' folder which I guess is as good a place as any.
my question is pretty much what the title suggests. my research has led me to try something like this:
import os
pathname = os.path.abspath("some/relative/directory")
print pathname
this problem is that whenever i do something like this, it simply returns whatever relative directory i gave it preceded by my python directory. for example:
C:\Python27\some\relative\directory
which is not even an existing directory on my computer. i understand that the python interpreter searches the working directory by default, but what i'd like to do is have it search my entire computer for an absolute path that contains the partial directory i specify.
the purpose of this is for me to create an exe (using py2exe) that can search for an arbitrary directory on any computer. is there a method for doing this in the standard library or through some available module - or would i have to implement the algorithm myself?
abspath is based on getcwd. Most likely, your current working directory simply isn't what you expect.
You can change the code that launches your script, change directories manually, or just use chdir in Python.
Did you try os.path.realpath("my/relative/dir")? Actually it seems the directory may not exist, but if it does, it will resolve symbolic links and whatnot.
I'm working on a really simple python package for our internal use, and want to package it as a .egg file, and when it's installed/used I want it to access a text file that is placed in an appropriate place on the computer.
So where is the best place to put application data in python? (that is meant to be edited by users) How do I get my python package to automatically install a default file there?
note: I know about the Windows application data directory, but would like to avoid it, as it's nonportable and kind of cumbersome both for users to access and for my application to access.
os.path.expanduser('~')
Each OS will have it's own directory where application data is expected to exist. There does not appear to be a method that provides this path in a platform-independent manner. You can write your own function to do this for you by checking os.name and then returning the appropriate value depending on the result.
I'm trying to run Python scripts using Xcode's User Scripts menu.
The issue I'm having is that my usual os.sys.path (taken from ~/.profile) does not seem to be imported when running scripts from XCode the way it is when running them at the Terminal (or with IPython). All I get is the default path, which means I can't do things like
#!/usr/bin/python
import myScript
myScript.foo()
Where myScript is a module in a folder I've added to my path.
I can append a specific path to os.sys.path manually easily enough, but I have to do it in every single script for every single path I want to use modules from
Is there a way to set this up so it uses the same path I use everywhere else?
EDIT: After looking into things a bit more, it seems like scripts executed from Xcode use a completely different PATH than normal. The path I get by running a script in Xcode is:
PATH=/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
and I'm sure my regular path doesn't have /Developer/usr/bin in it. Does anybody have any idea where this path is coming from?
On the mac, environment variables in your .profile aren't visible to applications outside of the terminal.
If you want an environment variable (like PATH, PYTHONPATH, etc) to be available to xcode apps, you should add it to a new plist file that you create at ~/.MacOSX/environment.plist.
See the EnvironmentVars doc on the apple developer website for more details.
A quick but hackish way is to have a wrapper script for python.
cat > $HOME/bin/mypython << EOF
#!/usr/bin/python
import os
os.path = ['/list/of/paths/you/want']
EOF
and then start all your XCode scripts with
#!/Users/you/bin/mypython
Just add the paths to sys,path.
>>> import sys
>>> sys.path
['', ... lots of stuff deleted....]
>>> for i in sys.path:
... print i
...
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python25.zip
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-darwin
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-mac
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-mac/lib-scriptpackages
/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-tk
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-dynload
/Library/Python/2.5/site-packages
/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC
>>> sys.path.append("/Users/crm/lib")
>>> for i in sys.path:
... print i
...
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python25.zip
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-darwin
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-mac
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/plat-mac/lib-scriptpackages
/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-tk
/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-dynload
/Library/Python/2.5/site-packages
/System/Library/Frameworks/Python.framework/Versions/2.5/Extras/lib/python/PyObjC
/Users/crm/lib
>>>
I tend to use pth files. From the docs.
The most convenient way is to add a
path configuration file to a directory
that’s already on Python’s path,
usually to the .../site-packages/
directory. Path configuration files
have an extension of .pth, and each
line must contain a single path that
will be appended to sys.path. (Because
the new paths are appended to
sys.path, modules in the added
directories will not override standard
modules. This means you can’t use this
mechanism for installing fixed
versions of standard modules.)
So the simplest thing to do is to do the following:
echo "/some/path/I/want/to/add" > /Library/Python/2.5/site-packages/custom.pth
HTH
Forgive me if my answer seems ignorant, I'm not totally familiar with Mac and I also may have misunderstood your question.
On Windows and Linux, when I want to refer to a script I've written, I set the PYTHONPATH environment variable. It is what os.sys.path gets its values from, if I remember correctly.
Let's say myScript.py is in /Somewhere. Set PYTHONPATH to:
PYTHONPATH = /Somewhere
Now you should be able to "import myScript".
If you start doing sub-folders as python packages, look into usage of init.py files in each folder.
If you plan on re-using this and other scripts all the time, you should leave PYTHONPATH set as an environment variable.
Not sure if Xcode counts as launching the script through Finder or not, but if it does, apparently Finder doesn't read .profile or .cshrc files when it starts for a user the way Terminal does.
If your question is unanswered still, check out Apple's knowledge base: QA1067 and set up your environment using the plist.