Reputation: 35
I know how there is a post on the same question but it is for Java. I am working with Python and so far I see no posts similar but I made an app and have a custom installer for it. The download install procedure all went well but the only issue is with the fact that after installation ends the desktop shortcut is not there for users to use. For me I tried manually creating a desktop shortcut, upload to the resource server and the installer should use wget to drop it on the user's desktop. I used Powershell to fetch desktop location with
desktopLocation=str(os.system('powershell.exe [Environment]::GetFolderPath(""""Desktop"""")'))
but wget seems to not get it and asks user to enter desktop directory everytime. So my question will be if there is any way to make wget understand my plan here or is there other ways to locally build a desktop shortcut based on the user's desktop location. Problem with just inserting "%userprofile%\Desktop" can be found here.
Upvotes: 1
Views: 1158
Reputation: 438153
os.system()
doesn't allow you to capture output from the shell command launched (only the command's exit code is returned) - instead, the output streams are passed through to the console.
Use subprocess.run()
instead (Python v3.5+; the command below is v3.6+ due to use of encoding identifier 'oem'
), which gives you detailed control over the call:
import subprocess
# ...
desktopLocation = subprocess.run(
[ 'powershell.exe', '-noprofile', '-c', '[Environment]::GetFolderPath("Desktop")' ],
capture_output=True,
encoding='oem'
).stdout.strip()
Note:
By passing the arguments individually, Python takes care of synthesizing the command line for you (on Windows), including any required escaping; you may alternatively specify a single command-line string as shown below, but then you'll have to do embedded quoting and escaping yourself.
No shell (cmd.exe
) is involved in the call by default; use shell=True
if you do want to call via cmd.exe
.
An object is returned whose .stdout
property contains the captured stdout output, which - thanks to the encoding
argument -is already decoded into a string (by default, you'd get a byte array on which you'd have to call .decode()
later to convert it to a string).
chcp
) for encoding its output, which in turn defaults to the system's active OEM code page, as determined by the system locale (language for non-Unicode programs).chcp 65001
) first, and decoded with .decode('utf8')
in Python. Windows 10 now allows you set both the OEM and the ANSI code page to UTF-8 system-wide, but this has far-reaching consequences; also, the feature is still in beta as of this writing - see this answer..strip()
is used to trim the trailing newline from the output.
In older Python versions and in simple cases, you can use a legacy method such as subprocess.check_output()
:
import subprocess
# ...
desktopLocation = subprocess.check_output(
'powershell.exe -noprofile -c [Environment]::GetFolderPath(\'Desktop\')'
).decode('oem')
Note:
As with subprocess.run()
, no shell is involved, unless shell=True
is also specified, and you may alternatively pass the executable and its arguments individually, as the elements of an array, as shown above.
The trailing newline is automatically stripped.
The merged stdout and stderr output is returned; the exit code cannot be examined; however, a nonzero exit code causes the call to fail.
Character-encoding caveat:
Encoding identifier 'oem'
requires v3.6+; in earlier 3.x versions, use an explicit code-page name (e.g., '437
on US-English systems) or determine the active OEM code page programmatically.
In v2.x, this decoding doesn't work, resulting in misinterpreted non-ASCII characters, presumably, because .check_output()
directly returns a string, which is where the misinterpretation happens. I don't know how to fix this problem.
Upvotes: 1