I've made a game and I'd like to save the highscore. So I need a place to do that. I chose to put it in the C:\All Programs directory. My problem is that that directory name isn't the same on every computer. For example on mine it's C:/Program Files (x86).
So my question:
Is there a way, to discover that path on any computer?
PROBLEM SOLVED:
os.getenv('PROGRAMFILES')
I second #iCodez's answer to use os.getenvto get the path string from a system environment variable, but you might want to use the paths defined for APPDATA or LOCALAPPDATA instead.
Windows permissions settings on the Program Files directory may prevent a standard user account from writing data to the directory.
I believe the APPDATA and LOCALAPPDATA paths were designed for just such a use. On my system, APPDATA = C:\Users\myname\AppData\Roaming and LOCALAPPDATA = C:\Users\myname\AppData\Local. My user account has full read/write permission for both directories.
You could use os.getenv or os.environ:
>>> import os
>>>> os.getenv('PROGRAMFILES')
'C:\\Program Files'
>>> os.environ['PROGRAMFILES']
'C:\\Program Files'
>>>
Note that you can also specify a default return value for when an environment variable is not set:
>>> os.getenv('BADVAR', 'default')
'default'
>>> os.environ.get('BADVAR', 'default')
'default'
>>>
Related
Let us say a user input is an invalid directory. if so how can I make a script automatically set a default directory to a local file or the desktop?
You have to use the os library and check if a directory exists:
isFile = os.path.isdir(path)
if isFile is false then set it to whatever default directory you want. If you want it to be set to Desktop, then use:
os.environ['USERPROFILE'] + '\Desktop'
docs: https://docs.python.org/3/library/os.html#os.environ
You can use
os.path.exists(path)
to see if it exists. If it does not, you can set set another path.
If you want to change directory, you can use
os.chdir(path)
I have imported a existing filesystem folder as the new project folder in eclipse. I have a script which get the current working directory path of the code. I need to change directory location to acccess files in other directory related to it. But It is giving different value when executed from eclipse and from the command line. Location is same in both place. Please help me resolve this issue. Operating system is windows here
import os
print os.getcwd()
os.chdir(os.path.dirname(os.getcwd()))
print os.getcwd()
One result is this
C:\Automation\trunk\Base\TestScripts
C:\Automation\trunk\Base
Other result is this
C:\Automation\trunk\UsefulScripts
C:\Automation\trunk
Second result is the one I expect, and that is where the code is located exactly.
watch out you cannot rely on that. Do the following :
basedir = os.environ.get('PROJECT_LOC', None)
if not basedir:
basedir = sys.path[0] # We are on commandline. sys.path OK
Then use basedir to find your files
Update
you have to specify this variable in the runtime of the interpreter
window->preferences->PyDev->Interpreters->Python Interpreter TAB (environment) There you can specify PROJECT_LOC referring to project_loc by selecting NEW with name PROJECT_LOC and variable (the other button) and selecting project_loc.
For some reasons those variables are not visible in python.
You can check this now with
def read_all_variables():
for key in os.environ.keys():
print ("%30s %s" % (key,os.environ[key]))
PROJECT_LOC should be there now
I have used the sys package instead of os. It works as expected.
import os,sys
currentpath = sys.path[0]
print currentpath
I can able to run it from eclipse and also from command line to get the correct path. Thanks for the help .
I'd like to define a constant in my script like that path to my Dropbox folder. Most my scripts will try to load some data of Dropbox which is shared among my PCs, but I find that between Mac and Ubuntu the prefix is different (/Users/<user>/Dropbox versus /home/<user>/Dropbox).
Is there a way to save this kind of information in some variable that will be loaded in each session such that I could have a global variable like DROPBOX (what would be a good convention, __DROPBOX__?) as path prefix to a file name, e.g. fname = DROPBOX + "myfile.txt".
Kind of reminds of me defining this in one's .Rprofile which holds settings in R.
Or is there a better way to handle this?
You could use the built in environment variables to get the path to the user home directory:
import os
print os.environ['HOME']
Which would solve your problem is a way that is more likely to remain stable if run on a new machine.
How about this:
os.path.expanduser('~/Dropbox')
or you can just try different alternatives:
dirs_to_try = ('/Users/Guido/Dropbox', '/home/Guido/Dropbox')
for path in dirs_to_try:
if os.path.isdir(path):
break
finally:
print 'cannot find Dropbox directory'
path = None
I see that if we change the HOME (linux) or USERPROFILE (windows) environmental variable and run a python script, it returns the new value as the user home when I try
os.environ['HOME']
os.exp
Is there any way to find the real user home directory without relying on the environmental variable?
edit:
Here is a way to find userhome in windows by reading in the registry,
http://mail.python.org/pipermail/python-win32/2008-January/006677.html
edit:
One way to find windows home using pywin32,
from win32com.shell import shell,shellcon
home = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, None, 0)
I think os.path.expanduser(path) could be helpful.
On Unix and Windows, return the argument with an initial component of ~ or ~user replaced by that user‘s home directory.
On Unix, an initial ~ is replaced by the environment variable HOME if it is set; otherwise the current user’s home directory is looked up in the password directory through the built-in module pwd. An initial ~user is looked up directly in the password directory.
On Windows, HOME and USERPROFILE will be used if set, otherwise a combination of HOMEPATH and HOMEDRIVE will be used. An initial ~user is handled by stripping the last directory component from the created user path derived above.
If the expansion fails or if the path does not begin with a tilde, the path is returned unchanged.
So you could just do:
os.path.expanduser('~user')
from pathlib import Path
str(Path.home())
works in Python 3.5 and above. Path.home() returns a Path object providing an API I find very useful.
I think os.path.expanduser(path) is the best answer to your question, but there's an alternative that may be worth mentioning in the Unix world: the pwd package. e.g.
import os, pwd
pwd.getpwuid(os.getuid()).pw_dir
For windows;
import os
homepath = os.path.expanduser(os.getenv('USERPROFILE'))
will give you a handle to current user's home directory and
filepath = os.path.expanduser(os.getenv('USERPROFILE'))+'\\Documents\\myfile.txt'
will give you a handle to below file;
C:\Users\urUserName\Documents\myfile.txt
home_folder = os.getenv('HOME')
This should work on Windows and Mac OS too, works well on Linux.
Really, a change in environment variable indicates that the home must be changed. So every program/script should have the new home in context; also the consequences are up to the person who changed it.
I would still stick with
home = os.getenv('USERPROFILE') or os.getenv('HOME')
what exactly is required?
I realize that this is an old question that has been answered but I thought I would add my two cents. The accepted answer was not working for me. I needed to find the user directory and I wanted it to work with and without sudo. In Linux, my user directory is "/home/someuser" but my root directory is "/root/". However, on my Mac, the user directory is "/Users/someuser". Here is what I ended up doing:
_USERNAME = os.getenv("SUDO_USER") or os.getenv("USER")
_HOME = os.path.expanduser('~'+_USERNAME)
This worked both with and without sudo on Mac and Linux.
get (translated) user folder names on Linux:
from gi.repository import GLib
docs = GLib.get_user_special_dir(GLib.USER_DIRECTORY_DOCUMENTS)
desktop = GLib.get_user_special_dir(GLib.USER_DIRECTORY_DESKTOP)
pics = GLib.get_user_special_dir(GLib.USER_DIRECTORY_PICTURES)
videos = GLib.get_user_special_dir(GLib.USER_DIRECTORY_VIDEOS)
music = GLib.get_user_special_dir(GLib.USER_DIRECTORY_MUSIC)
downloads = GLib.get_user_special_dir(GLib.USER_DIRECTORY_DOWNLOAD)
public = GLib.get_user_special_dir(GLib.USER_DIRECTORY_PUBLIC_SHARE)
templates = GLib.get_user_special_dir(GLib.USER_DIRECTORY_TEMPLATES)
print(docs)
print(desktop)
print(pics)
print(videos)
print(music)
print(downloads)
print(public)
print(templates)
On Linux and other UNIXoids you can always take a peek in /etc/passwd. The home directory is the sixth colon-separated field in there. No idea on how to do better than the environment variable on Windows though. There'll be a system call for it, but if it's available from Python, ...
In relation to another question, how do you account for paths that may change? For example, if a program is calling a file in the same directory as the program, you can simply use the path ".\foo.py" in *nix. However, apparently Windows likes to have the path hard-coded, e.g. "C:\Python_project\foo.py".
What happens if the path changes? For example, the file may not be on the C: drive but on a thumb drive or external drive that can change the drive letter. The file may still be in the same directory as the program but it won't match the drive letter in the code.
I want the program to be cross-platform, but I expect I may have to use os.name or something to determine which path code block to use.
Simple answer: You work out the absolute path based on the environment.
What you really need is a few pointers. There are various bits of runtime and environment information that you can glean from various places in the standard library (and they certainly help me when I want to deploy an application on windows).
So, first some general things:
os.path - standard library module with lots of cross-platform path manipulation. Your best friend. "Follow the os.path" I once read in a book.
__file__ - The location of the current module.
sys.executable - The location of the running Python.
Now you can fairly much glean anything you want from these three sources. The functions from os.path will help you get around the tree:
os.path.join('path1', 'path2') - join path segments in a cross-platform way
os.path.expanduser('a_path') - find the path a_path in the user's home directory
os.path.abspath('a_path') - convert a relative path to an absolute path
os.path.dirname('a_path') - get the directory that a path is in
many many more...
So combining this, for example:
# script1.py
# Get the path to the script2.py in the same directory
import os
this_script_path = os.path.abspath(__file__)
this_dir_path = os.path.dirname(this_script_path)
script2_path = os.path.join(this_dir_path, 'script2.py')
print script2_path
And running it:
ali#work:~/tmp$ python script1.py
/home/ali/tmp/script2.py
Now for your specific case, it seems you are slightly confused between the concept of a "working directory" and the "directory that a script is in". These can be the same, but they can also be different. For example the "working directory" can be changed, and so functions that use it might be able to find what they are looking for sometimes but not others. subprocess.Popen is an example of this.
If you always pass paths absolutely, you will never get into working directory issues.
If your file is always in the same directory as your program then:
def _isInProductionMode():
""" returns True when running the exe,
False when running from a script, ie development mode.
"""
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) #tools/freeze
def _getAppDir():
""" returns the directory name of the script or the directory
name of the exe
"""
if _isInProductionMode():
return os.path.dirname(sys.executable)
return os.path.dirname(__file__)
should work. Also, I've used py2exe for my own application, and haven't tested it with other exe conversion apps.
What -- specifically -- do you mean by "calling a file...foo.py"?
Import? If so, the path is totally outside of your program. Set the PYTHONPATH environment variable with . or c:\ or whatever at the shell level. You can, for example, write 2-line shell scripts to set an environment variable and run Python.
Windows
SET PYTHONPATH=C:\path\to\library
python myapp.py
Linux
export PYTHONPATH=./relative/path
python myapp.py
Execfile? Consider using import.
Read and Eval? Consider using import.
If the PYTHONPATH is too complicated, then put your module in the Python lib/site-packages directory, where it's put onto the PYTHONPATH by default for you.
I figured out by using os.getcwd(). I also learned about using os.path.join to automatically determine the correct path format based on the OS. Here's the code:
def openNewRecord(self, event): # wxGlade: CharSheet.<event_handler>
"""Create a new, blank record sheet."""
path = os.getcwd()
subprocess.Popen(os.path.join(path, "TW2K_char_rec_sheet.py"), shell=True).stdout
It appears to be working. Thanks for the ideas.