What is the use of os.getenv("HOME") in QFileDialog creation? - python

Like I said in the title I don't get what os.getenv("HOME") does in this code. I am following a course on an online site and the tutor was coding an interface with PyQt5 similar to notepad. I searched for an answer but they are a bit too advanced I guess. Also I have no idea what an environment variable is. By the way this is my first question on stack so excuse me for any possible mistakes and insufficient information.
def open_file(self):
file_name=QFileDialog.getOpenFileName(self,"Open File",os.getenv("HOME"))
with open(file_name[0],"r") as file:
self.writing_ar.setText(file.read())
The function above is connected to a button self.open such as self.open.clicked.connect(self.open_file)
And self.writing_ar is a QTextEdit object

In the case of os.getenv('HOME'), it's a UNIX-centric way to get the current user's home directory, which is stored as an environment variable per POSIX specification. A typical home directory location is /Users/yourname on MacOS, or /home/yourname on Linux, or c:\Users\Your Name on Windows -- so that's what this code is trying to look up.
The set of environment variables is effectively a key/value store, mapping strings to other strings, that is copied from any program to other processes it starts; they're thus a way to share configuration and other information between programs (though it only shares information down the tree, propagated only on process creation; changes made by a child process are not seen by its parent; and changes to a parent's environment after a child is started are not seen by the child).
If you want something that works reliably even on Windows, consider os.path.expanduser("~") instead. Thus, your code might become:
file_name = QFileDialog.getOpenFileName(self,
"Open File",
os.path.expanduser("~"))
See also What is the correct cross-platform way to get the home directory in Python?

It basically gets an environment variable for you and cast that onto a python variable.
From the code you shared, there should be a variable defined at the operating system level named HOME.
In Linux, that can be done with
export HOME="something_here"
You can check that this variable has actually been defined by typing
echo "$HOME"
in the terminal.
You can think of the os.getenv() method like it "echoes" the value of that argument onto some variable.

Related

Vim & Syntastic: Is it possible to switch Python version per project?

I know it's possible to choose which Python version to check e.g. in vim.rc as per this SO answer, but can I do it per project? Using e.g. virtualenv or a configuration file?
It all depends on how you define "this is a project".
Several of us have been providing local vimrc plugins where a project definition is "all the files in this directory and its subdirectories". See this answer for more details and alternatives solutions on the subject: Vim: apply settings on files in directory
Note that lately I've been working on a different (and more lightweight) way (in most cases) to specify what a project is: https://github.com/LucHermitte/lh-vim-lib/blob/master/doc/Project.md (This is still highly experimental).
Reading the answer you've linked to... It only speaks about a global variable that permits to tune the behaviour of the plugin. If there was no other way but tuning this global option, you'd have needed to reset this global variable unconditionally in the local vimrc, or on a BufEnter autocommand. Fortunately, syntastic is project aware thanks to buffer local variables -- #lcd047 corrected me on this topic. This means that instead of resetting a global variable, you could instead set a buffer local variable depending on the current directory (or any other heuristic you could define in an autocommand -- without these plugins, you could simply listen for BufNew and BufRead event, but this won't support migration among machines, directories, etc).
Note that my local-vimrc plugin sources the current local vimrc configuration file every time we enter a buffer matching that configuration file. This means that if you don't add an anti-reinclusion guard, b:syntastic_python_python_exec would be reset every time you enter a buffer for which it has been defined. It shouldn't be that problematic here. Note also that I don't know how alternative plugins proceed.

Determine how environment variable was set

In Python I can access an environment variable as:
os.environ['FOO']
I would like to know if the variable was set previously via export or if it was set only for the current python script like so:
FOO=BAR python some-script.py
Basically I want to only use FOO if it was set like in the line above and not permanently defined per export.
Arguments to the python script itself unfortunately are no option here. This is a plugin and the parent application does not allow passing custom arguments it does not understand itself.
I was hoping I somehow could access the exact and full command (FOO=BAR python some-script.py) that started python but it appears like there is nothing like that. I guess if there was a feature like this it would be somewhere in the os or sys packages.
The environment is simply an array of C strings, there is no metainformation there which helps you find out whether or not the invoking shell had the variable marked for export or not.
On Linux, you could examine /proc/(pid)/environ of the parent PID (if you have suitable permissions) to see what's in the parent's permanent environment, but this is decidedly nonportable and brittle.
Spending time on this seems misdirected anyway; let the user pass the environment variable in any way they see fit.

Where should I write a user specific log file to (and be XDG base directory compatible)

By default, pip logs errors into "~/.pip/pip.log". Pip has an option to change the log path, and I'd like to put the log file somewhere besides ~/.pip so as not to clutter up my home directory. Where should I put it and be XDG base dir compatible?
Right now I'm considering one of these:
$XDG_DATA_HOME (typically $HOME/.local/share)
$XDG_CACHE_HOME (typically $HOME/.cache)
This is, for the moment, unclear.
Different software seem to handle this in different ways (imsettings puts it in $XDG_CACHE_HOME,
profanity in $XDG_DATA_HOME).
Debian, however, has a proposal which I can get behind (emphasis mine):
This is a recurring request/complaint (see this or this) on the xdg-freedesktop mailing list to introduce another directory for state information that does not belong in any of the existing categories (see also home-dir.proposal. Examples for this information are:
history files of shells, repls, anything that uses libreadline
logfiles
state of application windows on exit
recently opened files
last time application was run
emacs: bookmarks, ido last directories, backups, auto-save files, auto-save-list
The above example information is not essential data. However it should still persist on reboots of the system unlike cache data that a user might consider putting in a TMPFS. On the other hand the data is rather volatile and does not make sense to be checked into a VCS. The files are also not the data files that an application works on.
A default folder for a future STATE category might be: $HOME/.local/state
This would effectively introduce another environment variable since $XDG_DATA_HOME usually points to $HOME/.local/share and this hypothetical environment variable ($XDG_STATE_HOME?) would point to $HOME/.local/state
If you really want to adhere to the current standard I would place my log files in $XDG_CACHE_HOME since log files aren't required to run the program.

add a permanent directory to PYTHONPATH bug

I have tried to add a permanent directory from here but i didn't understand how to do it.
The answer states that:
You need to add your new directory to the environment variable PYTHONPATH, separated by a colon from previous contents thereof.
However I pressed the Windows_Start Button and the Pause/Break Button and in Advanced System Settings I went to Environment Variables
AND HERE'S THE PROBLEM
There is no Variable named PYTHONPATH to set-up a value there!!! It must be a bug!
These are the values that exist in my System variables
ComSpec
FP_NO_HOST_CHECK
NUMBER_OF_PROCESSORS
OS
Path
PATHEXT
PROCESSOR_ARCHITECTURE
PROCESSOR_IDENTIFIER
PROCESSOR_LEVER
PROCESSOR_REVISION
PSModulePath
TEMP
TMP
USERNAME
windir
windows_tracing_flags
windows_tracing_logfile
See my problem is that i use sys.path.append() to add the directory but once i restart the GUI i must re-input the command.
The solution aforementioned and linked states that i must find the PYTHONPATH and add the directory there but i have no Environment Variable named PYTHONPATH
How can i run around this problem?
EDIT
Create a file start-my-app.cmd using a text editor (Notepad is good, Word/Wordpad is bad). Copy the code above and replace the parts between ... with what you need. Double click start-my-app.cmd or type start-my-app.cmd in a command prompt (you need to be in the same folder as start-my-app.cmd for this to work). – Aaron Digulla
-->Like this
THIS IS HOW I DID IT. IS IT CORRECT? PLZ TELL ME
Go to Environment Variables
Click the New Button in System Variables
Fill in the variable details
It looks suspiciously easy to me in contrast to the answers i have received but it works and every time i open the GUI i dont have to append the path. If there is anything wrong with this solution plz tell me.
Thank you
You can create a new one; the comment above only means: "If there already is one, don't just overwrote the current value".
That said, I don't like changing global environment variables much. First of all, you must not forget to restart all command prompts because existing ones don't get new variables.
My preferred solution is to create a .cmd/.bat file which contains:
set PYTHONPATH=...whatever your code needs...
python ...and start your Python code here...
That way the variable will be there when you expect it, no matter when and from where you start the script and it will not interfere with other stuff that you might also have.

Determining a file's path name from different working directories in python

I have a python module that is shared among several of my projects (the projects each have a different working directory). One of the functions in this shared module, executes a script using os.spawn. The problem is, I'm not sure what pathname to give to os.spawn since I don't know what the current working directory will be when the function is called. How can I reference the file in a way that any caller can find it? Thanks!
So I just learned about the __file__ variable, which will provide a solution to my problem. I can use file to get a pathname which will be constant among all projects, and use that to reference the script I need to call, since the script will always be in the same location relative to __file__. However, I'm open to other/better methods if anyone has them.
Put it in a well known directory (/usr/lib/yourproject/ or ~/lib or something similar), or have it in a well known relative path based on the location of your source files that are using it.
The following piece of code will find the location of the calling module, which makes sense from a programmer's point of view:
## some magic to allow paths relative to calling module
if path.startswith('/'):
self.path = path
else:
frame = sys._getframe(1)
base = os.path.dirname(frame.f_globals['__file__'])
self.path = os.path.join(base, path)
I.e. if your project lives in /home/foo/project, and you want to reference a script 'myscript' in scripts/, you can simply pass 'scripts/myscript'. The snippet will figure out the caller is in /home/foo/project and the entire path should be /home/foo/projects/scripts/myscript.
Alternatively, you can always require the programmer to specify a full path, and check using os.path.exists if it exists.
You might find the materials in this PyCon 2010 presentation on cross platform application development and distribution useful. One of the problems they solve is finding data files consistently across platforms and for installed vs development checkouts of the code.

Categories

Resources