i'm new on python and pynotify i want to create a notify message that shows me a notification with python and pynotify but i have a problem, all examples i use on tutorials found on internet.
ex.
#!/usr/bin/python
import sys
import pynotify
if __name__ == "__main__":
if not pynotify.init("icon-summary-body"):
sys.exit(1)
n = pynotify.Notification(
"Hi There",
"welcome to stackoverflow!",
##dont remove the below line
"notification-message-im")
n.show()
or
#!/usr/bin/env python
import os
import pynotify
pynotify.init("random information")
s = os.popen("fortune -n 100 -s","r").read()
n = pynotify.Notification("Fortune",s)
n.show()
gives me always the same error
** (icmp.py:13188): WARNING **: Connection Closed
Traceback (most recent call last):
File "icmp.py", line 14, in <module>
n.show()
gio.Error: Connection Closed
What does it mean??
Thanks
Well, I am responding you a year after posting this question. You may have already got the solution. So I will answer for other people facing the problem.
I was working on one project which uses Pynotify and I encountered the same problem. After a lot of research I found out that I was calling my script with root user. If you are also running your script with root user, then it may be the problem. The problem is that root does not have a dbus session running. I guess it does not even own XScreen. I assume you want to use Dbus session that belongs to the logged in user.
Solution 1: Use gksu. GUI applications should be started with gksu, not su or sudo.
Solution 2: Add following to your script.
import os
os.environ['DISPLAY'] = ':0.0'
Solution 3: Add root user to dbus group. [Not Verified]
I hope it helps.
To me the only way for now to use notification while using sudo python is by calling notify-send with subprocess:
Desktop environment: xfce4
WIP method (Insecure): sudo -Eu root python2.7
import os, subprocess
SudoUser = os.environ['SUDO_USER']
DBUSAddress = "DBUS_SESSION_BUS_ADDRESS={}".format(os.environ['DBUS_SESSION_BUS_ADDRESS'])
NotiCommand='{} notify-send "Welcome" "{}"'.format(DBUSAddress, SudoUser)
CompleteCall = 'sudo -u {} {}'.format(SudoUser, NotiCommand)
subprocess.call(CompleteCall, shell=True)
There you go! In my case this problem is the result of the tight security in Arch based distros as debian base distros are more flexible or actually insecure. Because this is more like a hack and it uses "shell=True" it's not recommended.
Sometimes this can happen when there is too long of a gap between calling .init() and creating the notification. There is a timeout, and when you call pynotify.init() that can elapse. If you make sure you call it again immediately before issuing the notification, you should quell this error.
Related
I have an application that is time sensitive to the time on a remote server - it needs to be run at a particular instant. Looping and retrieving the server time continuously does not get me as close as i'd like. I am trying to retrieve the server time and update my system's time (Python 3.7, windows 10) in advance so the module can restart as close as possible to the server's time. I have found the SetSysemTime function in win32api.
Here is the two line module i created to test various approaches:
import win32api
win32api.SetSystemTime(2020,9,1,21,9,10,10,0)
When i run this i get the following error:
Traceback (most recent call last):
File "C:\Users\pinev\AppData\Local\Programs\Python\Python37\Projects\Threading Tests\settime.py", line 4, in
win32api.SetSystemTime(2020,9,1,21,9,10,10,0)
pywintypes.error: (1314, 'SetSystemTime', 'A required privilege is not held by the client.')
So it seems i have the right solution, but somehow the module's privilege needs to be changed in order for Win10 to process the request. I have researched ways to set the privilege in a Python module and can't seem to find anything that works. If anyone could could provide a solution or a reference it would be greatly appreciated.
Thanks in advance.
If you just need to elevate privileges to run Python programs, you can launch the program as an administrator.
This is also the simplest and most direct method I think.
Test code:
import win32api
import ctypes, sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
win32api.SetSystemTime(2020,9,1,21,9,10,10,0)
else:
# Re-run the program with admin rights
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
The following code throws an error if it's run by a non-root user for a file owned by root, even when the non-root user has sudo privileges:
try:
f = open(filename, "w+")
except IOError:
sys.stderr.write('Error: Failed to open file %s' % (filename))
f.write(response + "\n" + new_line)
f.close()
Is there a way to run open(filename, "w+") with sudo privileges, or an alternative function that does this?
You have a few options:
Run your script as root or with sudo
Set the setuid bit and have root own the script (although on many systems this won't work with scripts, and then the script will be callable by anyone)
Detect that you're not running as root (os.geteuid() != 0), then call yourself with sudo infront (which will ask the user to enter their password) and exit:
import os
import sys
import subprocess
if os.geteuid() == 0:
print("We're root!")
else:
print("We're not root.")
subprocess.call(['sudo', 'python3', *sys.argv])
sys.exit()
Calling it looks like this:
$ python3 be_root.py
We're not root.
Password:
We're root!
TL;DR:
L3viathan's reply has a SynaxError Edit: works fine on Python 3.5+. Here is a version for Python 3.4.3 (distributed by default on Ubuntu 16.04) and below:
if os.geteuid() == 0:
# do root things
else:
subprocess.call(['sudo', 'python3'] + sys.argv) # modified
However, I went with a different approach because it made the code around it simpler in my use case:
if os.geteuid() != 0:
os.execvp('sudo', ['sudo', 'python3'] + sys.argv)
# do root things
Explaination
L3viathan's reply depends on PEP 448, which was included in Python 3.5 and introduced additional contexts where star argument expansion is permitted. For Python 3.4 and below, list concatenation can be used to do the same thing:
import os
import sys
import subprocess
if os.geteuid() == 0:
print("We're root!")
else:
print("We're not root.")
subprocess.call(['sudo', 'python3'] + sys.argv) # modified
But note: subprocess.call() launches a child process, meaning after root finishes running the script, the original user will continue running their script as well. This means you need to put the elevated logic into one side of an if/else block so when the original script finishes, it doesn't try to run any of the logic that requires elevation (L3viathan's example does this).
This isn't necessarily a bad thing - it means both normal/elevated logic can be written in the same script and separated nicely - but my task required root for all the logic. I didn't want to waste an indentation level if the other block was going to be empty, and I hadn't realized how using a child process would affect things, so I tried this:
import os
import sys
import subprocess
if os.geteuid() != 0:
subprocess.call(['sudo', 'python3'] + sys.argv)
# do things that require root
...and it broke of course, because after root was done, the regular user resumed execution of its script and tried to run the statements that required root.
Then I found this Gist recommending os.execvp() - which replaces the running process instead of launching a child:
import os
import sys
if os.geteuid() != 0:
os.execvp('sudo', ['sudo', 'python3'] + sys.argv) # final version
# do things that require root
This appears to behave as expected, saves an indentation level and 3 lines of code.
Caveat: I didn't know about os.execvp() ten minutes ago, and don't know anything yet about possible pitfalls or subtleties around its usage. YMMV.
Another option is to write the file to a directory you have access to, then sudo mv the file to the directory you don't have access to.
Your script is limited to the permissions it is run with as you cannot change users without already having root privileges.
As Rob said, the only way to do this without changing your file permissions is to run with sudo.
sudo python ./your_file.py
Having possibility to using sudo don't give you any privileges if you don't actually use it. So as other guys suggested you probably should just start your program with use of sudo. But if you don't like this idea (I don't see any reason for that) you can do other trick.
Your script can check if is run with root privileges or if it work only with user privileges. Than script can actually run itself with higher privileges. Here you have an example (please note that storing password in source code isn't a good idea).
import os.path
import subprocess
password_for_sudo = 'pass'
def started_as_root():
if subprocess.check_output('whoami').strip() == 'root':
return True
return False
def runing_with_root_privileges():
print 'I have the power!'
def main():
if started_as_root():
print 'OK, I have root privileges. Calling the function...'
runing_with_root_privileges()
else:
print "I'm just a user. Need to start new process with root privileges..."
current_script = os.path.realpath(__file__)
os.system('echo %s|sudo -S python %s' % (password_for_sudo, current_script))
if __name__ == '__main__':
main()
Output:
$ python test.py
I'm just a user. Need to start new process with root privileges...
OK, I have root privileges. Calling the function...
I have the power!
$ sudo python test.py
OK, I have root privileges.
Calling the function...
I have the power!
I like L3viathan's reply. I'd add a fourth option: Use subprocess.Popen() to execute an sh command to write the file. Something like subprocess.Popen('sudo echo \'{}\' > {}'.format(new_line, filename)).
Python newbie here. So, please excuse if this has been asked before in a different format.
I am trying to replicate the following perl snippet in Python using the win32com module. This snippet is provided by Qualcomm for easier automation of their tools.
use Win32::OLE;
use Win32::OLE::Variant;
$prod_id = "QPSTAtmnServer.Application"; # AppId for the Automation server.
eval{ $qpst = Win32::OLE->GetActiveObject($prod_id)}; # Attempt to use a running instance.
die "$prod_id not installed" if $#;
unless (defined $qpst) { $qpst = Win32::OLE->new($prod_id, sub {$_[0]->Quit;}) or die "Cannot start $prod_id";} # Start a new instance. Call Quit when $qpst set to undef or script exits.
if (defined $qpst)
{
$port = $qpst->GetPort("COM30001");
}
The block of python code I have till now is as follows:
import win32com.client
import time
import os
cmd = 'cls'
os.system(cmd)
cmd = 'start C:\\LAB\\exe\\pskill.exe QPSTConfig'
os.system(cmd)
cmd = 'start C:\\LAB\\exe\\pskill.exe QPSTServer'
os.system(cmd)
cmd = 'start C:\\LAB\\exe\\pskill.exe AtmnServer'
os.system(cmd)
time.sleep(2)
_path = os.getcwd()
qpst = win32com.client.Dispatch('QPSTAtmnServer.Application')
time.sleep(5)
if (qpst is None):
print('Darn!')
else:
port = qpst.GetPort('30001')
print(port)
and it throws the following error:
Traceback (most recent call last):
File "xxxx.py", line 20, in module
port = qpst.GetPort('30001')
TypeError: 'NoneType' object is not callable
After reading a couple of posts it seems like the method (GetPort) is not registering as a method after all.
Is that correct analysis?
If yes, how do I make Python interpret it as a method?
If not, what is going on here with the error?
Thanks in advance for the help!
It looks like I had to do couple of things to solve the issue.
Use the makepy command on the "AtmnServer" OLE TypeLibrary file to create a *.py file in:
...\Python27\Lib\site-packages\win32com\gen_py\
Add an extra line to actually interpret the required Method as a method (instead of as a property/attribute or something) :
qpst._FlagAsMethod("GetPort")
before the line:
port = qpst.GetPort("COM30001")
Thanks again for offering to help!
Correct, it is saying that GetPort does not exist. Have you checked that the Perl version works? If you don't have Perl, you could try through Excel's VBA (open its VBA console -- you may have to enable it by following the steps here). If you can dispath the QPST from Excel VBA and do the GetPort, then something is very odd.
It could be that QPST COM interface changed since this script was written. You could try
qpst = win32com.client.gencache.EnsureDispatch(
'QPSTAtmnServer.Application')
which will attempt to create the type library for QPST. Sometimes it finds extra objects, but if not at very least you can then browse the QPST COM from python using combrowse.py (which is part of pywin32) and try to find where that function is. Combrowse is a basic COM browser, just run \Lib\site-packages\win32com\client\combrowse.py, if need more powerful the one from visual studio is probably better.
I'm having an interesting problem with threads and the tempfile module in Python. Something doesn't appear to be getting cleaned up until the threads exit, and I'm running against an open file limit. (This is on OS X 10.5.8, Python 2.5.1.)
Yet if I sort of replicate what the tempfile module is doing (not all the security checks, but just generating a file descriptor and then using os.fdopen to produce a file object) I have no problems.
Before filing this as a bug with Python, I figured I'd check here, as it's much more likely that I'm doing something subtly wrong. But if I am, a day of trying to figure it out hasn't gotten me anywhere.
#!/usr/bin/python
import threading
import thread
import tempfile
import os
import time
import sys
NUM_THREADS = 10000
def worker_tempfile():
tempfd, tempfn = tempfile.mkstemp()
tempobj = os.fdopen(tempfd, 'wb')
tempobj.write('hello, world')
tempobj.close()
os.remove(tempfn)
time.sleep(10)
def worker_notempfile(index):
tempfn = str(index) + '.txt'
# The values I'm passing os.open may be different than tempfile.mkstemp
# uses, but it works this way as does using the open() function to create
# a file object directly.
tempfd = os.open(tempfn,
os.O_EXCL | os.O_CREAT | os.O_TRUNC | os.O_RDWR)
tempobj = os.fdopen(tempfd, 'wb')
tempobj.write('hello, world')
tempobj.close()
os.remove(tempfn)
time.sleep(10)
def main():
for count in range(NUM_THREADS):
if count % 100 == 0:
print('Opening thread %s' % count)
wthread = threading.Thread(target=worker_tempfile)
#wthread = threading.Thread(target=worker_notempfile, args=(count,))
started = False
while not started:
try:
wthread.start()
started = True
except thread.error:
print('failed starting thread %s; sleeping' % count)
time.sleep(3)
if __name__ == '__main__':
main()
If I run it with the worker_notempfile line active and the worker_tempfile line commented-out, it runs to completion.
The other way around (using worker_tempfile) I get the following error:
$ python threadtempfiletest.py
Opening thread 0
Opening thread 100
Opening thread 200
Opening thread 300
Exception in thread Thread-301:
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 460, in __bootstrap
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 440, in run
File "threadtempfiletest.py", line 17, in worker_tempfile
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 302, in mkstemp
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 236, in _mkstemp_inner
OSError: [Errno 24] Too many open files: '/var/folders/4L/4LtD6bCvEoipksvnAcJ2Ok+++Tk/-Tmp-/tmpJ6wjV0'
Any ideas what I'm doing wrong? Is this a bug in Python, or am I being bone-headed?
UPDATE 2009-12-14:
I think I've found the answer, but I don't like it. Since nobody was able to replicate the problem, I went hunting around our office for machines. It passed on everything except my machine. I tested on a Mac with the same software versions I was using. I even went hunting for a Desktop G5 with the EXACT same hardware and software config I had -- same result. Both tests (with tempfile and without tempfile) succeeded on everything.
For kicks, I downloaded Python 2.6.4, and tried it on my desktop, and same pattern on my system as Python 2.5.1: tempfile failed, and notempfile succeeded.
This is leading me to the conclusion that something's hosed on my Mac, but I sure can't figure out what. Any suggestions are welcome.
I am unable to reproduce the problem with (Apple's own build of) Python 2.5.1 on Mac OS X 10.5.9 -- runs to completion just fine!
I've tried both on a Macbook Pro, i.e., an Intel processor, and an old PowerMac, i.e., a PPC processor.
So I can only imagine there must have been a bug in 10.5.8 which I never noticed (don't have any 10.5.8 around to test, as I always upgrade promptly whenever software update offers it). All I can suggest is that you try upgrading to 10.5.9 and see if the bug disappears -- if it doesn't, I have no idea how this behavior difference between my machines and yours is possible.
I think your answer can be found here. You have to explicitly os.close() the file descriptor given as the first part of the tuple that mkstemp gives you.
Edit: no, the OP is already doing what is supposed to be done. I'm leaving the answer up for the nice link.
I just tested your code on my Ubuntu Linux computer here, and it worked perfectly for me.
I have one suggestion for you to try. I don't know that it will help but it can't hurt. Rewrite your code to use with:
from __future__ import with_statement
def worker_tempfile():
tempfd, tempfn = tempfile.mkstemp()
with os.fdopen(tempfd, 'wb') as tempobj:
tempobj.write('hello, world')
os.remove(tempfn)
time.sleep(10)
The with statement is supposed to make sure that the file object gets closed no matter what. Perhaps it might help?
Good luck. Great job on the question, by the way.
Why do you think the error is not genuine? You are launching 10000 threads, each opening a file, while the maximum number of open files is typically 1024 under Unix systems.
First try to keep manually track of the number of files currently open and check whether it bumps past the OS limit.
Since nobody was able to replicate the problem, I went hunting around our office for machines. It passed on everything except my machine. I tested on a Mac with the same software versions I was using. I even went hunting for a Desktop G5 with the EXACT same hardware and software config I had -- same result. Both tests (with tempfile and without tempfile) succeeded on everything.
For kicks, I downloaded Python 2.6.4, and tried it on my desktop, and same pattern on my system as Python 2.5.1: tempfile failed, and notempfile succeeded.
This is leading me to the conclusion that something's hosed on my Mac, so this isn't likely to be a problem that anyone else runs into ever.
Thanks VERY much to everyone (especially Alex Martelli) who helped on this!
So I am trying to open a URL in Epiphany WebBrowser [ let's say for example http://www.google.com ] from a python script. My python script is as follows:
import os
string = "DISPLAY=:0 xdg-open http://www.google.com"
os.system(string)
It returns the error: xdg-open: no method available for opening 'http://www.google.com'
However if I type DISPLAY=:0 xdg-open http://www.google.com into LXTerminal is works fine. It also works remotely through SSH.
Any Ideas? Also can someone explain to me why a command works fine in terminal, but not when you try to call them from a Python script using os.system()?
UPDATE -- NEED HELP STILL
NOTE: All files are located in /home/pi
After much frustration, I figured I would give the below method a try. I created a file called google.sh. The code for google.sh s as follows:
#google.sh
DISPLAY=:0 xdg-open http://www.google.com
when I call upon this program using ./google.sh from LXTerminal it works fine! Great so now let's call it from a python script called test.py whose code is as follows:
# test.py
import os
string = "/home/pi/google.sh"
os.system(string)
However for some reason it STILL returns: xdg-open: no method available for opening 'http://www.google.com'
how about this?
the idea, is to open a epiphany window and close it after 5 seconds.
import subprocess
from time import sleep
p = subprocess.Popen("exec epiphany-browser http://yahoo.com", stdout=subprocess.PIPE,shell=True)
sleep(5)
p.kill()
print("done")