Is there any way to make the computer a Python program is running on restart? Generic solution is good, but in particular I'm on windows.
There is no generic way of doing this, afaik.
For Windows, you need to access the Win32 API. Like so:
import win32api
win32api.InitiateSystemShutdown()
The win32api module is a part of pywin32.
For linux/os x, I guess calling the "reboot" command is the easiest.
import os
os.system('reboot now')
Or something like that.
(Note to downvoters: os.system() has not been deprecated. The text is "The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function." For simple cases like this, when you aren't interested in retrieving the results, nor in multiprocessing, os.system() works just fine).
Why don't you just call the shutdown command using subprocess?
You could reboot a Windows system by using: os.system("shutdown -t 0 -r -f")
Example:
import os
print("REBOOTING")
os.system("shutdown -t 0 -r -f")
Change the number in front of -t to change the number of seconds before shutdown.
There is nothing in the standard library that would directly allow you to do this, and I am unaware of any modules that provide a cross platform method, but if you are on Windows and don't want to install anything (like the win32api) then you could use ctypes default module and interact with the WinAPI directly.
You could use the ExitWindowsEx() function to restart the computer (it is almost the same as my other answer How to shudown a computer using Python; however the hexadecimal value has to be changed to restart and not shutdown).
Process:
First you need ctypes:
import ctypes
Next get the user32.dll as described in the documentation:
DLL | User32.dll
So:
user32 = ctypes.WinDLL('user32')
Next you need to call the ExitWindowsEx() function and insert the correct hexadecimal values:
user32.ExitWindowsEx(0x00000002, 0x00000000)
The first argument (0x00000002) shuts down the system and then restarts (see documentation).
The second argument (0x00000000) gives a reason to be logged by the system. A complete list can be found here
Complete Code:
import ctypes
user32 = ctypes.WinDLL('user32')
user32.ExitWindowsEx(0x00000002, 0x00000000)
About os.system() method on Windows:
The win32api or ctypes answers both will execute silently. os.system("shutdown -t 0 -r -f") will leave a message saying "You are about to be signed out in less than a minute" which may be undesirable in some cases.
A file alongside the script called shutdown.bat/shutdown.exe/shutdown.cmd will cause the command shutdown -t 0 -r -f to break, calling that file and not the system command. The same goes for described wmic.exe above.
As a side note: I built WinUtils (Windows only) which simplifies this a bit, however it should be faster (and does not require Ctypes) since it is built in C.
Example:
import WinUtils
WinUtils.Restart(WinUtils.SHTDN_REASON_MINOR_OTHER)
Related
I'm trying to convert a video between two file types, when run, nothing happens and no file is made. I've tried doing it with subprocess and os - both have the same result - nothing.
I can do the command fine through shell. I really want to be able to use this through python.
import subprocess
command = "ffmpeg -i X:/Desktop/twd.mp4 X:/Desktop/twd.mp3"
subprocess.run(command.split(),shell=True)
nothing happens and no file is made
This is very strange. Absolutely no text printed on console? I agree #Rotem's suggestion, but at the minimum the version info should print on your console (assuming you are using one of prebuilt binaries). BTW, shell=True is not needed and not recommended.
If you wish, you can give my ffmpegio package a try, it might make your life a bit easier.
import ffmpegio
ffmpegio.transcode('X:/Desktop/twd.mp4','X:/Desktop/twd.mp3')
It should auto detect your ffmpeg binaries and run your example above.
I am on mac OSX.
I have a program where I am trying to call downloaded libraries from the terminal. This is not possible if I don't know where the libraries are. I will use pip as a common library example
>>> os.system("pip -h")
32512
>>> os.system("which pip")
256
I have read this response to the 256 error, however, I still don't understand why it appears here. It says it is "frequently used to indicate an argument parsing failure" however the exact command works because this does not seem to be an argument parsing error to me.
I would like to be able to do something to the effect of:
os.system(os.system("which pip") +" -h")
If there is another way of doing this, I would love to hear it
Don't use os.system like that (and don't use which, either). Try this to find a program:
import os
for bin_dir in os.environ.get("PATH").split(":"):
if 'my_program' in os.listdir(bin_dir):
executable_path = os.path.join(bin_dir, 'my_program')
break
Note that this does assume that PATH was properly set by whatever process started the script. If you are running it from a shell, that shouldn't be an issue.
In general, using os.system to call common *NIX utilities and trying to parse the results is unidiomatic-- it's writing python as if it was a shell script.
Then, instead of using system to run pip, use the solution describe in this answer.
I am trying to compile a C program using Python and want to give input using "<" operator but it's not working as expected.
If I compile the C program and run it by giving input though a file it works; for example
./a.out <inp.txt works
But similarly if I try to do this using a Python script, it did not quite work out as expected.
For example:
import subprocess
subprocess.call(["gcc","a.c","-o","x"])
subprocess.call(["./x"])
and
import subprocess
subprocess.call(["gcc","a.c","-o","x"])
subprocess.call(["./x","<inp.txt"])
Both script ask for input though terminal. But I think in the second script it should read from file. why both the programs are working the same?
To complement #Jonathan Leffler's and #alastair's helpful answers:
Assuming you control the string you're passing to the shell for execution, I see nothing wrong with using the shell for convenience. [1]
subprocess.call() has an optional Boolean shell parameter, which causes the command to be passed to the shell, enabling I/O redirection, referencing environment variables, ...:
subprocess.call("./x <inp.txt", shell = True)
Note how the entire command line is passed as a single string rather than an array of arguments.
[1]
Avoid use of the shell in the following cases:
If your Python code must run on platforms other than Unix-like ones, such as Windows.
If performance is paramount.
If you find yourself "outsourcing" tasks better handled on the Python side.
If you're concerned about lack of predictability of the shell environment (as #alastair is):
subprocess.call with shell = True always creates non-interactive non-login instances of /bin/sh - note that it is NOT the user's default shell that is used.
sh does NOT read initialization files for non-interactive non-login shells (neither system-wide nor user-specific ones).
Note that even on platforms where sh is bash in disguise, bash will act this way when invoked as sh.
Every shell instance created with subprocess.call with shell = True is its own world, and its environment is neither influenced by previous shell instances nor does it influence later ones.
However, the shell instances created do inherit the environment of the python process itself:
If you started your Python program from an interactive shell, then that shell's environment is inherited. Note that this only pertains to the current working directory and environment variables, and NOT to aliases, shell functions, and shell variables.
Generally, that's a feature, given that Python (CPython) itself is designed to be controllable via environment variables (for 2.x, see https://docs.python.org/2/using/cmdline.html#environment-variables; for 3.x, see https://docs.python.org/3/using/cmdline.html#environment-variables).
If needed, you can supply your own environment to the shell via the env parameter; note, however, that you'll have to supply the entire environment in that event, potentially including variables such as USER and HOME, if needed; simple example, defining $PATH explicitly:
subprocess.call('echo $PATH', shell = True, \
env = { 'PATH': '/sbin:/bin:/usr/bin' })
The shell does I/O redirection for a process. Based on what you're saying, the subprocess module does not do I/O redirection like that. To demonstrate, run:
subprocess.call(["sh","-c", "./x <inp.txt"])
That runs the shell and should redirect the I/O. With your code, your program ./x is being given an argument <inp.txt which it is ignoring.
NB: the alternative call to subprocess.call is purely for diagnostic purposes, not a recommended solution. The recommended solution involves reading the (Python 2) subprocess module documentation (or the Python 3 documentation for it) to find out how to do the redirection using the module.
import subprocess
i_file = open("inp.txt")
subprocess.call("./x", stdin=i_file)
i_file.close()
If your script is about to exit so you don't have to worry about wasted file descriptors, you can compress that to:
import subprocess
subprocess.call("./x", stdin=open("inp.txt"))
By default, the subprocess module does not pass the arguments to the shell. Why? Because running commands via the shell is dangerous; unless they're correctly quoted and escaped (which is complicated), it is often possible to convince programs that do this kind of thing to run unwanted and unexpected shell commands.
Using the shell for this would be wrong anyway. If you want to take input from a particular file, you can use subprocess.Popen, setting the stdin argument to a file descriptor for the file inp.txt (you can get the file descriptor by calling fileno() a Python file object).
I am trying to write a script that will shut down the computer if a few requirements are filled with the command
os.system("poweroff")
also tried
os.system("shutdown now -h")
and a few others. but nothing happens when I run it, the computer goes through the code without crashing or producing any error messages and terminates the script normally, without shutting down the computer.
How does one shutdown the computer in python?
edit:
Seems that the commands I have tried requires root access. Is there any way to shut down the machine from the script without elevated privileges?
import os
os.system("shutdown now -h")
execute your script with root privileges.
Many of the linux distributions out there require super user privileges to execute shutdown or halt, but then, how come that if you're sitting on your computer you can power it off without being root? You open a menu, hit Shutdown and it shutdowns without you becoming root, right?
Well... the rationale behind this is that if you have physical access to the computer, you could pretty much pull the power cord and power it off anyways, so nowadays, many distributions allow power-off though access to the local System Bus accessible through dbus. Problem with dbus (or the services exposed through it, rather)? It's constantly changing. I'd recommend installing a dbus viewer tool such as D-feet (be advised: it's still pretty hard to visualize, but it may help)
Take a look to these Dbus shutdown scripts.
If you still have HAL in your distrubution (is on the way to being deprecated) try this:
import dbus
sys_bus = dbus.SystemBus()
hal_srvc = sys_bus.get_object('org.freedesktop.Hal',
'/org/freedesktop/Hal/devices/computer')
pwr_mgmt = dbus.Interface(hal_srvc,
'org.freedesktop.Hal.Device.SystemPowerManagement')
shutdown_method = pwr_mgmt.get_dbus_method("Shutdown")
shutdown_method()
This works on a Ubuntu 12.04 (I just powered off my computer to make sure it worked). If you have something newer... well, it may not work. It's the downside of this method: it is very distribution specific.
You might have to install the dbus-python package for this to work (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)
UPDATE 1:
I've been doing a little bit of research and it looks like this is done in newer Ubuntu versions through ConsoleKit. I've tested the code below in my Ubuntu 12.04 (which has the deprecated HAL and the newer ConsoleKit) and it did shut my computer off:
>>> import dbus
>>> sys_bus = dbus.SystemBus()
>>> ck_srv = sys_bus.get_object('org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager')
>>> ck_iface = dbus.Interface(ck_srv, 'org.freedesktop.ConsoleKit.Manager')
>>> stop_method = ck_iface.get_dbus_method("Stop")
>>> stop_method()
UPDATE 2:
Probably why can you do this without being root deserves a bit of a wider explanation. Let's focus on the newer ConsoleKit (HAL is way more complicated and messy, IMHO).
The ConsoleKit is a service running as root in your system:
borrajax#borrajax:/tmp$ ps aux|grep console-kit
root 1590 0.0 0.0 1043056 3876 ? Sl Dec05 0:00 /usr/sbin/console-kit-daemon --no-daemon
Now, d-bus is just a message passing system. You have a service, such as ConsoleKit that exposes an interface to d-bus. One of the methods exposed is the Stop (shown above). ConsoleKit's permissions are controlled with PolKit, which (despite on being based on regular Linux permissions) offers a bit of a finer grain of control for "who can do what". For instance, PolKit can say things like "If the user is logged into the computer, then allow him to do something. If it's remotely connected, then don't.". If PolKit determines that your user is allowed to call ConsoleKit's Stop method, that request will be passed by (or through) d-bus to ConsoleKit (which will subsequently shutdown your computer because it can... because it worth's it... because it's root)
Further reading:
What are ConsoleKit and PolicyKit? How do they work?
ArchWiki PolKit
To summarize: You can't switch a computer off without being root. But you can tell a service that is running as root to shutdown the system for you.
UPDATE 3:
On December 2021, seven years after the original answer was written I had to do this again. This time, in a Ubuntu 18.04.
Unsurprisingly, things seem to have changed a bit:
The PowerOff functionality seems to be handled via a new org.freedesktop.login1 service, which is part of the """new""" (cough! cough!) SystemD machinery.
The dbus Python package seems to have been deprecated and/or considered "legacy". There is, however, a new PyDbus library to be used instead.
So we can still power off machines with an unprivileged script:
#! /usr/bin/python3
from pydbus import SystemBus
bus = SystemBus()
proxy = bus.get('org.freedesktop.login1', '/org/freedesktop/login1')
if proxy.CanPowerOff() == 'yes':
proxy.PowerOff(False) # False for 'NOT interactive'
Update 3.1:
It looks like it's not as new as I thought X-D
There's already an answer by #Roeften in this very same thread.
BONUS:
I read in one of your comments that you wanna switch the computer off after a time consuming task to prevent it from overheating... Did you know that you can probably power it on at a given time using RTC? (See this and this) Pretty cool, uh? (I got so excited when I found out I could do this... ) :-D
The best way to shutdown a system is to use the following codes
import os
os.system('systemctl poweroff')
any way to shut down...without elevated privileges?
No, there isn't (fortunately!).
Keep in mind that you can use several system features to make privilege escalation for normal users easier:
sudo
setuid
setcap
Just to add to #BorrajaX 's answer for those using logind (newer fedora systems):
import dbus
sys_bus = dbus.SystemBus()
lg = sys_bus.get_object('org.freedesktop.login1','/org/freedesktop/login1')
pwr_mgmt = dbus.Interface(lg,'org.freedesktop.login1.Manager')
shutdown_method = pwr_mgmt.get_dbus_method("PowerOff")
shutdown_method(True)
linux:
import subprocess
cmdCommand = "shutdown -h now"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)
Windows:
import subprocess
cmdCommand = "shutdown -s"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)
In case you want to execute it from root, #Rahul R Dhobi answer works great:
import os
os.system("shutdown now -h")
Execution: sudo python_script.py
In case you need to execute it without root privileges:
import subprocess
import shlex
cmd = shlex.split("sudo shutdown -h now")
subprocess.call(cmd)
Execution: $ python_script.py # no sudo required
try this
import os
os.system("sudo shutdown now -h")
this worked for me
I'am using Fedora and it works with me. all what i need to do is Writing this line in terminal :
$ sudo python yourScript.py
There is a way to shut down the computer without using elevated permissions.
import os
subprocess.call(['osascript', '-e', 'tell app "system events" to shut down'])
When I launch a PowerShell script from Python, the delay seems to be approximately 45s, and I cannot figure out why.
I'm trying to run a PowerShell script (accessing some APIs only available to PowerShell) from a Python script.
I've tried a lot of permutations, and all incur ~45 second delay compared to just running the script from a command prompt, using an identical command line.
For example - sample.ps1 might say:
echo foo
And runner.py might say:
import subprocess
p = subprocess.Popen([POWERSHELL, '-File', 'sample.ps1'], stdout=subprocess.STDOUT)
d = p.stdout.read()
Running the .ps1 script directly is fast, running it via runner.py (Python 2.7, 32bit on a 64bit machine) incurs 45 second delay.
The exact same thing occurs if I use "os.system", or Twisted's built-in process tools. So I suspect it's some subtle interaction between the Python interpreter and the Powershell interpreter, possibly related to creation of console windows, or handling of stdin/out/err streams? (which I know don't "really exist" in the same way on Windows)
I do not see any such delays. It is pretty snappy. ( that will also depend on what your script actually does.) Try using call:
from subprocess import call
call(["powershell", "sample.ps1"])
PowerShell loads your user's profile by default. Use the -NoProfile argument to turn that behavior off:
import subprocess
p = subprocess.Popen([POWERSHELL, '-NoProfile', '-File', 'sample.ps1'], stdout=subprocess.STDOUT)
d = p.stdout.read()