Execute an .exe in Python in Ubuntu/WSL - python

How can I execute an .exe file with Python3 on Ubuntu in WSL? From my searches I found os.system, but despite being placed in the correct folder, I cannot find the .exe file. I also tried with os.open with no results.
import os
current = os.chdir('../../../Programmi/OWASP/Zed Attack Proxy/')
os.system("ZAP.exe")

To expound on #MichaelMatsaev's answer a bit, what you are attempting to do with the Python example in your question is essentially the same as this Bash construct:
cd ../../../Programmi/OWASP/Zed Attack Proxy/
ZAP.exe
You'll get a command not found from Bash. Pretty much every Linux app will work the same way, since they all ultimately use some form of syscall in the exec family.
When executing any binary in Linux (not just Windows .exe's in WSL), the binary must be either:
On the search $PATH
Specified with a fully-qualified (relative or absolute) path to the binary.
So in addition to #MichaelMatsaev's (correct) suggestion to use:
os.system("../../../Programmi/OWASP/Zed Attack Proxy/ZAP.exe")
The following would work as well:
os.chdir('../../../Programmi/OWASP/Zed Attack Proxy/')
os.system("./ZAP.exe")
And, while it would be a bit pathologic (i.e. I can't imagine you'd want to do it) for this case, you could even modify the search path inside the code and then call the binary without a fully-qualified path:
os.environ['PATH'] += os.pathsep + '../../../Programmi/OWASP/Zed Attack Proxy/'
os.system("ZAP.exe")
Side-note: AFAIK, there's no reason to attempt to store the os.chdir into the current variable, as os.chdir doesn't return a value.

Try using a fully-qualified path:
os.system("../../../Programmi/OWASP/Zed Attack Proxy/ZAP.exe")

Related

Is there a difference between running a python script via a relative and an absolute path?

I'm getting a weird error that depends on whether I run the same Python 2.7 script from a relative or absolute path.
In other words, if I have a python script located in c:\tmp\git\enigma\blah.py and my current directory is in c:\tmp\otherdir, this works:
python ..\git\enigma\blah.py some_args
but this fails:
python c:\tmp\git\enigma\blah.py some_args
The script does run in both cases, and uses subprocess.Popen in both cases to call another program, changing the directory to what I think is the same place, but something fails if I use an absolute path to invoke Python.
I'm double checking the script --- I didn't write it --- to see if it relies on the current working directory anywhere, but it's suspicious that the two cases are different.
Aside from looking if the program uses sys.argv[0], can anyone suggest things to look at which might depend on this difference?
OK, so it looks like the issue is the command this script is executing (yarn) seems to depend on case-sensitivity of the drive letter in Windows.
I am located in C:\tmp\git\enigma. If I use a relative path, it picks up the correct drive letter. If I use an absolute path python c:\tmp\git\enigma\blah.py, then the spawned process seems to get confused. If I use python C:\tmp\git\enigma\blah.py then it works ok.
Still checking why this should matter.... never mind, it's not a Python thing.

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();

Locating a resource file in the same directory

I am building an application that needs access to a resource in the same folder (It needs the xsd file to validate the input file).
How can I reach this xsd file reliably?
To elaborate:
I need to be able to call the executable:
cd not/the/directory/of/the/program
path/to/program -c config.xml
What is the path to use here?
subprocess.Popen("xmllint --noout --schema ?/?/config.xsd " + configfilename)
Take a look at the zeroth command-line argument your program gets. It's usually the name of the program, and might also include a path to the program. Combine that with the current directory. Then use realpath or some equivalent of it to get rid of symbolic links. However, I think there are still some corner cases where this approach might fail.
You didn't specify /the programming language/ or operating system you are using. If you're writing a bash script, see here:
https://stackoverflow.com/a/246128/11451509
For Python, see How do I get the path of the current executed file in Python?
If the operating system is Linux, you could also go through the /proc pseudo filesystem, as explained here:
https://stackoverflow.com/a/738024/11451509

Change %PATH% from Python Script (Windows)

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"?

Python os.system() call runs in incorrect directory

My coworker is having trouble with a Python install. When running the code below, from 'C:\my\folder\', 'C:\' is returned instead of the current working directory. When I or anyone else run the script on our systems, we get 'C:\my\folder\'.
We're assuming that some global setting must be causing the issue, so I've had the person uninstall Python, delete the local Python2.7 folder, clean the registry and reinstall the Python, but it's still not working.
NOTE: We have a large number of legacy scripts, so revising all of them to use subprocess is impractical. :(
Any ideas?
Environment: Windows XP, Python 2.7
import os
#
# This test script demonstrates issue on the users computer when python invokes
# a subshell via the standard os.system() call.
#
print "This is what python thinks the current working directory is..."
print os.getcwd()
print
print
print "but when i execute a command *from* python, this is what i get for the current working directory"
os.system('echo %cd%')
raw_input()
you could also try something like this
os.chdir("C:\\to\\my\\folder")
print os.system("echo %CD%")
raw_input()
also to get the current working directory i use a different approach
cur_dir = os.path.abspath(".")
os.getcwd() isn't guarenteed to get the location of your script when it is called. Your coworker might be calling the script a different way or his computer (for some reason) handles the current working directory differently.
To get the actual script location you should use the following:
import os
os.path.dirname(os.path.realpath(__file__))
As an example I wrote getcwd and the above line in the same script and ran it from C:\.
Results:
C:\>python C:\Users\pies\Desktop\test.py
C:\Users\pies\Desktop
C:\
It depends on what your real purpose for this script is, whether you actually need the current working directory, or just the current scripts directory. As a little caveat this call will return a different directory if you call a script from script which then uses this call.
os.system("cd dir;command params")

Categories

Resources