Change %PATH% from Python Script (Windows) - python

As part of a project, I need to ensure that a few paths are included in the user's %PATH% variable, which I am going to do at the beginning of the script. What's the best way to do this from a python script?
My first thought was to just use something like the following:
subprocess.call('path = %PATH%;c:\path1;c:\path2;c:\path3')
To add each of the paths, as this is how you would do it from the Windows command line, though my fear is that after a reboot these settings would not carry over (this is what seems to happen when I run it from the command line regularly - in order for it to stick, I actually have to go in through the GUI and change it).
Anyone have a better idea, or will this work as I'd like it to? (Ideally, the user will only have to execute this portion of the script once, at which point the 'setup' will be complete and not need to be run again)
Thanks!

path = os.environ.get('PATH')
subprocess.call('setx /M PATH "' + path + ';c:\path1;c:\path2;c:\path3"')
...or use _winreg. Example from another question here: How to add to and remove from system's environment variable "PATH"?

Related

Java ProcessBuilder cant run ".\venv\Scripts\active" in windows

Using Java's ProcessBuilder, I try to run a python script with activating virtual environment but i'm getting error like '.\venv\Scripts\activate" "' is not recognized as an internal or external command.
In command window cmd, I can use ".\venv\Scripts\activate" directly with no problem but in my code at below, error occured.
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c","cd C:\\Users\\onurc\\PycharmProjects\\OCR", "& .\\venv\\Scripts\\activate", "& python main.py");
That command doesn't look valid to me. You may be confused about what ProcessBuilder does / how windows (or any OS) works.
When you type a command in a dosbox or terminal, you're sending it to the shell - on linux, probably /bin/bash, or zsh or whatnot. On windows, you're sending it to cmd.exe. That program (so, bash or cmd) then decodes what you typed and does all sorts of fancy things to it, and then it in turns asks the underlying kernel to actually go run that app.
Java's ProcessBuilder does not invoke cmd/bash/zsh, it is a sibling to cmd/bash/zsh - it also does some fancy things, but far fewer fancy things. On windows, even the OS (or rather, the tool) does some fancy things whereas on linux it does not.
In general, trying to even guess whether the tool you run does fancy things, and which fancy things java's ProcessBuilder does, is not a sound way to write dependable software. Especially considering the relative hardship of testing this, given that it involves invoking external stuff.
Hence, you should opt out. Of all the fancy things. Thus:
Always call the command with a complete and absolute path.
Always use the multi-string/list version, never rely on java to split on spaces.
Never use *, ? or any other glob. Write out each and every parameter in full.
Do not try to use > or & or any other 'symbol that means something specific'. An OS doesn't support any of this stuff - you just pass [A] the full path to an executable and [B] a bunch of strings that the kernel will directly pass to the process without doing any processing on it. If you want to do stuff to standard out, error out, or standard in - then use Process's methods to do this.
Those &s in your command sure look like shellisms to me.
To fix:
You can tell the process which directory to run in, so there is no need for a cd command.
You should write the absolute path to CMD.exe. You can ask the environment. You're now relying on a combination of a properly configured PATH + the undefined behaviour of the JVM that does a bare minimum of fancy things (turning relative paths to absolute ones by PATH-scanning is a 'fancy thing' you should not be relying on).
I don't know what that & thing is, but you don't want that.
If activate is a script (shouldn't that end in .bat or .js or .vbs or whatnot?), run that, then run python separately. If activate sets things in the local environment table, make a script file that runs both and run the script instead.
Running python is not a good idea. Run C:\whatever\python.exe.
You have the right idea for activate, more or less (you're in a known dir and then write an actual path. If python.exe is guaranteeed to be in that OCR dir, run .\\python.exe, not python.
Convert command as a single string instead of passing separate arguments to the ProcessBuilder.
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c","cd C:\\Users\\onurc\\PycharmProjects\\OCR & .\\venv\\Scripts\\activate & python main.py");
Another way could be, if all command has to run under same folder, then change ProcessBuilder working directory using directory method:
Path rootDir = Paths.get("C:\\Users\\onurc\\PycharmProjects\\OCR");
ProcessBuilder processBuilder = new ProcessBuilder("cmd", "/C", ".\\venv\\Scripts\\activate & python main.py");
processBuilder.directory(rootDir.toFile());
Process process = processBuilder.start();
process.waitFor();

Autoimport of modules from IDLE home directory

I am aware of the difference between import x and from x import yyy, in the latter case one can address x-located functions by bare name, instead of full specification, and this exactly I want to do, I do not want to write full name every time.
Also I know how to redefine default Python dir on Windows so that it starts knowing my developed modules, and this is fine. However how to combine those two things altogether?
I want IDLE to get started knowing all functions from all my modules so I do not need to import them manually.
from * import *
i.e. for all modules in IDLE home directory?
P.S. I saw this question, however it puts solution only for one import and do not scan the whole dir, also this solution with shortcut parameters does not seem beautiful to me.
Are there any more neat ways?
If you start idle with -r file it will first run the file, or with -s, it will first run the file listed in the IDLESTARTUP or PYTHONSTARTUP environmental variables. Then test by starting IDLE in command prompt with, for instance, py -m idlelib -r file. Once this works, you could create on IDLE shortcut on your desktop (drag and drop from Start menu), open Properties, and add either of the above to the end of the 'Target'.

How to make a python program run just by typing the name alone at the terminal?

I am not sure what I am supposed to be searching, because everything I have been trying to look up has not really given me the answers that I need.
If anyone can point me in the right direction of exactly what I should be looking at, I would greatly appreciate it. Basically, I want to know the best way to go about making a python program which I can distribute (not publicly).
Once someone has the file they run a script, or run the make command, and the result of this would be that the user can invoke the program from within any directory on the computer by just typing the name (and passing args) in the terminal.
I only know of one way to do this, which I believe is the wrong way. My idea was something as follows:
1.) A main folder, let's call it Ghoul. It would contain 3 files:
setup.sh
ghoul.sh
ghoul.py
2.) The user would have to run setup.sh, which would make ghoul.sh an executable and it would change the name to ghoul and then I would move it to /bin
3.) Within the ghoul file which is now in /bin, the file itself would contain "python /home/user/Ghoul/ghoul.py $#" And this would allow the program to run from any directory just by typing "ghoul"
I hope it's clear what I am trying to accomplish, I know this can't be the appropriate way of doing this. What should I be looking up and reading on to accomplish this? I would like to know how I can do this on Ubuntu and if also ..Windows.
I am also interested if I can limit the "ghoul" command to work only in the Ghoul directory, but of course in any directory that is within the Ghoul directory instead of from within any directory on the system.
Thank you.
On Unix like systems
#! /usr/bin/env python
in the very first line of your chmod +x script file will make it executable from the current directory using ./filename
If you want completely straightforward execution from anywhere you can put it on the path somewhere however you choose.
On windows its more complicated, if you want commandline execution the default install should give you the ability to execute
myscript.py
If its in your path. to drop the .py you need to get .py into the PATHEXT variable. Alternatively if it neds to be distributed to someone without any python install check out www.py2exe.org

Python off a Flash Drive, how to start IDLE?

I was trying to run Python 3.3 off of my flash drive. I already tried Portable Python, but most of what it had wouldn't open, and it crashed my laptop.
So, I deleted it, and installed regular Python. Then, I wanted to start adding my favorite modules. And, I needed a way to start IDLE without the original shortcut.
To install modules, I added my Python install to my PATH variable.
To make all this easier, I made a batch file, using some code I found on this question.
So far, I have this. It also asks for the drive letter, because that changes from computer to computer.
#echo off
echo This only works if your Python install is added to the system-wide PATH variable
set /p Path="Enter the Drive Letter on this computer. No Symbols, Just the Letter, Capital"
cd %Path%:\Program Files\Python33
echo type this when python comes up...
echo import idlelib.PyShell
echo idlelib.PyShell.main()
echo.
echo.
echo.
echo.
python
It outputs this:
If you go on and follow the instructions and type what it says, it brings up IDLE.
I couldn't figure out how to get the batch file to actually type into the Python prompt, so I told it to tell the user to type what needed to be typed.
What I need to know is, how can I change the PATH variable from within the batch file. Also, how to I remove it when I'm done (this isn't as important, and could even be in a separate batch file).
Or, alternatively, is there a way just to shortcut to IDLE?
Also, is there a way to run .py files without the command line, with the Python install on my flash drive?
Thanks!
You can invoke Python with this command line:
python -c"import idlelib.PyShell;idlelib.PyShell.main()"
and it will bring-up IDLE shell without the need for the user to type anything.
Edit: BTW, Are you sure you really need to change the global path settings. Try to see if the following script can start Python the way you want. You must put it in the root of the USB drive where you have your Python installation.
#echo off
setlocal
set SCRIPT_DIR=%~dp0
:: Removes trailing backslash (for readability in the following)
set SCRIPT_DIR=%SCRIPT_DIR:~0,-1%
set PYTHON_HOME=%SCRIPT_DIR%\Program Files\Python33
set PATH=%PYTHON_HOME%;%PATH%
"%PYTHON_HOME%\python.exe" -c"import idlelib.PyShell;idlelib.PyShell.main()"
Edit: Every process has an associated environment, which is a set of name-value pairs called environment variables. When a process is started it gets a copy of the environment of its parent process. The global OS settings for environment variables are used for processes started directly from the OS (GUI or command line) shell. The set command in batch files sets or modifies an environment variable in the environment of the current process (not globally).
All the set commands you see in the above script change only the environment of the current process. These changes will be seen by the process created by the last line (python.exe) because it is a child process of the command shell (cmd.exe) process that is executing the batch-file.
The line
set PATH=%PYTHON_HOME%;%PATH%
prepends the content of the PYTHON_HOME variable to the PATH variable of the current process. For example, if PATH were c:\foo\bar;d:\aaa\bbb and PYTHON_HOME were c:\python then the new value of PATH will be c:\python;c:\foo\bar;d:\aaa\bbb
It can not be guaranteed this is possible unless you have high enough system privileges that you can change the global path. There is really no way around this on most computers that you do not own, which I imagine is the main purpose. In those cases when you have enough privileges (it is worth a try some systems still allow this for regular users but many others do not) you can use:
setx PATH "%path%;yourpath"
edit and ps:
You can figure out the drive letter without input, if you know the disk label, with something like this:
#echo off
set label=DRIVENAME
set cmd=WMIC logicaldisk WHERE volumename^^="%label%" GET caption
FOR /F "tokens=1" %%G IN ('%cmd% ^| find ":"')DO set pydrive=%%G
echo %pydrive%\pathtopython
rem do your stuff here
the idle started inside the batch will inherit path but other instances will not. Hard to test conclusively tough.
Explanation of the batch script above. The command wmic is short for windows management instrumentation commandline. One can use WMI to do many things one of them is to issue WQL (SQL for WMI) queries as if windows would be a a database. Databases contain many tables in this case the computer is instructed to fetch the table named logicaldisk. Table logicaldisk has 38 columns and one row for each disk connected to the system. This is way to much data for this purpose. So the data is filtered. WHERE causes the database only to spit out rows that contain some specific value in this case its only interested in rows where column volumename ins equal to DRIVENAME, likewise you could use serial number size or any other criteria. Lastly GET is used to limit the columns you get back as results since your only interested in the letter name of the drive that's what you ask. That is called a caption in the table so that what you ask.
Since the command is a bit long, so i put the command inside a variable (not the result) this shortens the for line so it fits stack overflow. Since = need to be escaped i need to use the escape sequence ^ too times so it still es capable in the for loop.
The for loop is used to capture the return value of the wmic command. Since the answer has many lines i filter for only the lines which contain a colon character. And put it to variable pydrive.

Default working directory for Python IDLE?

Is there a configuration file where I can set its default working directory? It currently defaults to my home directory, but I want to set it to another directory when it starts. I know I can do "import os" followed by "os.chdir("")" but that's kind of troublesome. It'd be great if there is a conf file that I can edit and change that setting, but I am unable to find it.
In particular, I've looked into my OS (Ubuntu)'s desktop entry '/usr/share/applications/idle-python3.2.desktop', which doesn't contain a conf file, but points to '/usr/lib/python3.2/idlelib/PyShell.py', which points to config-*.def conf files under the same folder, with 'config-main.def' being the most likely candidate. However I am unable to find where the default path is specified or how it can be changed.
It seems that the path is hard-coded in PyShell.py, though I could be wrong with my limited knowledge on Python. I will keep looking, but would appreciate it if somebody knows the answer on top of his or her head. Thanks in advance.
I actually just discovered the easiest answer, if you use the shortcut link labeled "IDLE (Python GUI)". This is in Windows Vista, so I don't know if it'll work in other OS's.
1) Right-click "Properties".
2) Select "Shortcut" tab.
3) In "Start In", write file path (e.g. "C:\Users...").
This is also my answer here: Default save path for Python IDLE? Let me know if this works!
I've found a solution after looking into PyShell.py:
Create a python file under a preferred directory, in my case '~/.idlerc/init.py', and copy/paste the following lines:
import os
os.chdir('<your preferred directory>')
Pass "-r '~/.idlerc/init.py' " argument to the IDLE startup command, like the following (your exec location and name may vary depending on OS, etc):
/usr/bin/idle-python3.2 -n -r ~/.idlerc/init.py
Just use a shell script such as:
#!/bin/bash
cd /Users/pu/Projects/L-Python
/usr/bin/idle
and run that instead of stock idle. The example is on OS X, adapt to your system.
I'm new to python and learning from 'Dive into Python' by mark Pilgrim (can be found online free)
the answer is in chapter 2.4 - hope he doesn't mind me pasting it here as its also plugging his book and is in the GPL
Before you go any further, I want to briefly mention the library
search path. Python looks in several places when you try to import a
module. Specifically, it looks in all the directories defined in
sys.path. This is just a list, and you can easily view it or modify it
with standard list methods. (You'll learn more about lists later in
this chapter.)
Example 2.4. Import Search Path
import sys
sys.path
sys.path.append('/my/new/path')
It's a good book I am a programmer - usually I find learning from books sends me quickly to sleep - not the case here ....
All I had to do here (Linux Mint 18.2 Xfce) ...
Just add path in line "working directory" = "Arbeitsverzeichnis"
It can change depending on where you installed Python. Open up IDLE, import os, then call os.getcwd() and that should tell you exactly where your IDLE is working on.
One default path is specified in idlelib.IOBinding.IOBinding.dirname or idlelib.IOBinding.IOBinding.filename
Ubuntu
So my idle-python3.desktop
file in /usr/share/applications looks like this:
[Desktop Entry]
Name=IDLE (using Python-3)
Comment=Integrated Development Environment for Python (using Python-3)
Exec=python3 -c "import idlelib.IOBinding, os; idlelib.IOBinding.IOBinding.dirname='/DEFAULT/DIRECTORY';import idlelib.idle"
Icon=/usr/share/pixmaps/python3.xpm
Terminal=false
Type=Application
Categories=Application;Development;
StartupNotify=true
To use it you need to set /DEFAULT/DIRECTORY to your desired directory, copy it with root rights into /usr/share/applications. You can also use it for Python 2 but then you need to replace the 3s with 2s.
ConfigFiles
There are also extensions that can be loaded. These must be modules and you specify them by module name. The config files for IDLE are located in HOME/.idlerc and parsed with a configparser. I did not get further with this.
Here's a way to reset IDLE's default working directory for MacOS if you launch Idle as an application by double-clicking it. You need a different solution if you launch Idle from a command line in Terminal. This solution is a permanent fix. You don't have to rechange the directory everytime you launch IDLE. I wish it were easier.
The idea is to edit a resource file inside of the IDLE package in Applications.
Start by finding the the file. In Finder, go to IDLE in Applications (in the Python folder) as if you wanted to open it. Right click and select "show package contents". Open Contents, then open Resources. In Resources, you'll see a file called idlemain.py. This file executes when you launch idle and sets, among other things, the working directory. We're going to edit that.
But before you can edit it, you need to give yourself permission to write to it. To do that, right click on the idlemain.py and select get info. Scroll to the bottom of the getinfo window and you'll see the Sharing & Permissions section. On the bottom right there's a lock icom. Click the lock and follow the prompts to unlock it. Once it's unlocked, look to the left for the + (under the list of users with permissions). Click it. That will bring up a window with a list of users you can add. Select yourself (probably the name of your computer or your user account) and click Select. You'll see yourself added to the list of names with permissions. Click where is says "Read only" next to your name and change it to "Read & Write". Be careful not to change anything else. When you're done, click the lock again to lock the changes.
Now go back to idlemain.py and open it with any text editor (you could use Idle, TextEdit, or anything. Right under the import statement at the top is the code to change the default working directory. Read the comment if you like, then replace the single line of code under the comment with
os.chdir('path of your desired working directory')
Mine looks like this:
os.chdir('/Users/MyName/Documents/Python')
Save your changes (which should work because you gave yourself permission). Next time you start Idle, you should be in your desired working directory. You can check with the following commands:
import os
os.getcwd()
This ought to be the number one answer. I have been playing around this for an hour or more and nothing worked. Paul explains this perfectly. It's just like the PATH statement in Windows. I successfully imported a module by appending my personal "PythonModules" path/dir on my Mac (starting at "/users/etc") using a simple
import xxxx command in Idle.

Categories

Resources