Close Python IDLE shell without prompt - python-2.7

I am working on a script (script A), that needs to open a new Python IDLE shell, automatically run another script (script B) in it and then close it. The following code is what I use for this purpose:
import sys
sys.argv=['','-n','-t','My New Shell','-c','execfile("VarLoader.py")']
import idlelib.PyShell
idlelib.PyShell.main()
However I can't get the new shell close automatically. I have tried adding the following to script B but either it doesn't close the new shell or a windows pops up asking whether I want to kill it.
exit()
.
import sys
sys.exit()

Instead of monkeypatching or modifying the IDLE source code to make your program skip the prompt to exit I'd recommend you create a subclass of PyShell that overrides the close method how you want it to work:
import idlelib.PyShell
class PyShell_NoExitPrompt(idlelib.PyShell.PyShell):
def close(self):
"Extend EditorWindow.close(), does not prompt to exit"
## if self.executing:
## response = tkMessageBox.askokcancel(
## "Kill?",
## "Your program is still running!\n Do you want to kill it?",
## default="ok",
## parent=self.text)
## if response is False:
## return "cancel"
self.stop_readline()
self.canceled = True
self.closing = True
return idlelib.PyShell.EditorWindow.close(self)
The original issue with this was that then using idlelib.PyShell.main would not use your subclass, you can in fact create a copy of the function - without modifying the original - by using the FunctionType constructor that will use your modified class:
import functools
from types import FunctionType
def copy_function(f, namespace_override):
"""creates a copy of a function (code, signature, defaults) with a modified global scope"""
namespace = dict(f.__globals__)
namespace.update(namespace_override)
new_f = FunctionType(f.__code__, namespace, f.__name__, f.__defaults__, f.__closure__)
return functools.update_wrapper(f, new_f)
Then you can run your extra IDLE shell like this:
import sys
#there is also a way to prevent the need to override sys.argv but that isn't as concerning to me.
sys.argv = ['','-n','-t','My New Shell','-c','execfile("VarLoader.py")']
hacked_main = copy_function(idlelib.PyShell.main,
{"PyShell":PyShell_NoExitPrompt})
hacked_main()
Now you can leave IDLE the way it is and have your program work the way you want it too. (it is also compatible with other versions of python!)

Related

ROS: saving object in a file when a ros node is killed

I am running a rosnode with a kalman filter running. The kalman filter is an object with states that get updated as time plays out. Conventionally, a ros node has a run(self) method that runs at a specified frequency using the while condition
while not rospy.is_shutdown():
do this
Going through each loop my kalman filter object updates. I just want to be able to save the kalman filter object when the node is shutdown either some external condition or when the user presses ctrl+C. I am not able to do this. In the run(self) method, I tried
while not rospy.is_shutdown():
do this
# save in file
output = pathlib.Path('path/to/location')
results_path = output.with_suffix('.npz')
with open(results_path, 'xb') as results_file:
np.savez(results_file,kfObj=kf_list)
But it has not worked. Is it not executing the save command? If ctrl+C is pressed does it stop short of executing it? Whats the way to do it?
Check out the atexit module:
http://docs.python.org/library/atexit.html
import atexit
def exit_handler():
output = pathlib.Path('path/to/location')
results_path = output.with_suffix('.npz')
with open(results_path, 'xb') as results_file:
np.savez(results_file,kfObj=kf_list
atexit.register(exit_handler)
Just be aware that this works great for normal termination of the script, but it won't get called in all cases (e.g. fatal internal errors).
Why not try the following python example class structure engaging shutdown hooks :
import rospy
class Hardware_Interface:
def __init__(self, selectedBoard):
...
# Housekeeping, cleanup at the end
rospy.on_shutdown(self.shutdown)
# Get the connection settings from the parameter server
self.port = rospy.get_param("~"+self.board+"-port", "/dev/ttyACM0")
# Get the prefix
self.prefix = rospy.get_param("~"+self.board+"-prefix", "travel")
# Overall loop rate
self.rate = int(rospy.get_param("~rate", 5))
self.period = rospy.Duration(1/float(self.rate))
...
def shutdown(self):
rospy.loginfo("Shutting down Hardware Interface Node...")
try:
rospy.loginfo("Stopping the robot...")
self.controller.send(0, 0, 0, 0)
#self.cmd_vel_pub.publish(Twist())
rospy.sleep(2)
except:
rospy.loginfo("Cannot stop!")
try:
self.controller.close()
except:
pass
finally:
rospy.loginfo("Serial port closed.")
os._exit(0)
This just an extract from a personal script, please modify it to your needs. I imagine that the on_shutdown will do the trick. Another similar approach comes from my friends in the Robot Ignite Academy in The Construct and seems like that
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
class my_class():
def __init__(self):
...
self.cmd = Twist()
self.ctrl_c = False
self.rate = rospy.Rate(10) # 10hz
rospy.on_shutdown(self.shutdownhook)
def publish_once_in_cmd_vel(self):
while not self.ctrl_c:
...
def shutdownhook(self):
# works better than the rospy.is_shutdown()
self.ctrl_c = True
def move_something(self, linear_speed=0.2, angular_speed=0.2):
self.cmd.linear.x = linear_speed
self.cmd.angular.z = angular_speed
self.publish_once_in_cmd_vel()
if __name__ == '__main__':
rospy.init_node('class_test', anonymous=True)
...
This is obviously a sample of their code (for more please join the academy)

Error ALDialog Python Nao

I have a problem when using the ALDialog module on Python IDE and to load on Nao. I tried in different ways to load a dialogue but I always fall back on the same error.Runtimeerror LoadTopic::ALDialogIncorrect file myDialog.topIn the first case I write directly the text that I save in a. top file but at the time of LoadTopic () I have an error.In the second case I want to load the. top file by giving it the path. I come back to the same mistake again.Do you have a solution to my problem?Thank you very much.
import qi
import argparse
import os
import sys
from naoqi import ALProxy
def main(robot_ip, robot_port):
dialog = """
topic: ~myTopic() \n
language: enu \n
u:(test) hello \n """
file = open("myDialog.top","w")
file.write(dialog)
file.close()
# load topic
proxy = ALProxy("ALDialog",robot_ip,robot_port)
proxy.setLanguage("English")
self.topic = proxy.loadTopic("myDialog.top")
# start dialog
proxy.subscribe("myModule")
# activate dialog
proxy.activateTopic(self.topic)
if name == "main":
parser = argparse.ArgumentParser()
parser.add_argument("--ip", type=str,
default="169.254.245.164",help="Robot's IP address : '169.254.245.164'")
parser.add_argument("--port", type=int, default=9559,help="port number, the default value is OK in most cases")
args = parser.parse_args()
main(args.ip, args.port)
ALDialog.loadTopic expects an absolute filepath on the robot - it doesn't know anything about the context from which you're calling it (it could be from another computer, in which case of course it can't open that file). You need to be sure that your .top is indeed on the robot, and pass it's absolute path to ALDialog.
Once installed on the robot this path will be something like /home/nao/.local/share/PackageManager/apps/your-package-id/your-dialog-name/your-dialog-name_enu.top

pygame program exits with no error message when run with pythonw

I'm trying to run a pygame program using pythonw to avoid having the console window show up. This causes a weird issue related to print statements.
Basically, the program will just exit after a few seconds with no error message. The more printing I do, the faster it happens.
If I run it in idle or at the command prompt (or in linux) the program works fine. This problem only happens when launched with pythonw (right-click, Open With, pythonw).
I'm using python 2.7.11 on Windows XP 32-bit. pygame 1.9.1release.
Is there a workaround for this? Why does the program simply terminate with no error?
import pygame
from pygame.locals import *
succeeded, failed = pygame.init()
display_surface = pygame.display.set_mode((320, 240))
clock = pygame.time.Clock()
terminate = False
while terminate is False:
for event in pygame.event.get():
if event.type == QUIT:
terminate = True
area = display_surface.fill((0,100,0))
pygame.display.flip()
elapsed = clock.tick(20)
print str(elapsed)*20
pygame.quit()
You don't need to remove print statements. Save them for later debugging. ;-)
Two steps to solve this problem:
Firstly, keep all the code in py file - don't change it to pyw now; Say it is actualCode.py
Then, create a new file runAs.pyw with the following lines in it
# In runAs.pyw file, we will first send stdout to StringIO so that it is not printed
import sys # access to stdout
import StringIO # StringIO implements a file like class without the need of disc
sys.stdout = StringIO.StringIO() # sends stdout to StringIO (not printed anymore)
import actualCode # or whatever the name of your file is, see further details below
Note that, just importing actualCode runs the file, so, in actualCode.py you should not enclose the code which is executed, in what I call is it main running file condition. For example,
# In actualCode.py file
....
....
....
if __name__ == '__main__': # Don't use this condition; it evaluates to false when imported
... # These lines won't be executed when this file is imported,
... # So, keep these lines outside
# Note: The file in your question, as it is, is fine

How to redirect from a python script to another scripts taking user input

I have 2 python scripts Script1.py and Script2.py respectively. I create another script called Value.py in which I want to take a user input as either Script1 as a string which would run Script1.py or Script2 which would run Script2.py.
Please can someone help me out in making this short script.
Thanks
Rather than running the scripts separately, you should encapsulate their contents into a function and either:
Put all three functions into one .py file (if they're short); or
import the two existing functions into value.py (if they're long).
Then value simply looks like:
from Script1 import func1 # only for option 2
from Script2 import func2 # only for option 2
def value():
...
if user_input == "Script1":
func1()
else:
func2()
def func1(): # only for option 1
...
def func2(): # only for option 1
...
value() # call value

Call current PyMOL session from python script

I'm trying to call current PyMOL session from python script (wxpython GUI), and then load some data from PyMOL and send few commands to PyMOL. At the moment I can open a new PyMOL session in python script:
import sys, os
from wx import *
app = wx.App()
dialog = wx.FileDialog ( None, message = 'Set PyMOL directiry', style = wx.OPEN)
if dialog.ShowModal() == wx.ID_OK:
# Pymol path
moddir = dialog.GetDirectory()
sys.path.insert(0, moddir)
os.environ['PYMOL_PATH'] = moddir
import pymol
pymol.finish_launching()
else:
print 'Nothing was selected.'
from pymol import *
dialog1 = wx.FileDialog ( None, message = 'Set PDB file', style = wx.OPEN)
if dialog1.ShowModal() == wx.ID_OK:
pdbfile = dialog1.GetPath()
cmd.load(pdbfile)
else:
print 'Nothing was selected.'
dialog.Destroy()
app.MainLoop()
BUT actually I'd like to check in my python scrip whether any PyMOL session is already opened.
I found discussion corresponding to this topic here:
Only call function if PyMOL running
Following this discussion I tried to call 'print' function in PyMOL:
try:
from pymol import cmd
print 'Connected'
except:
<open new Pymol sesssion>
but I do not see any text in PyMOL cmd. I tried to determine PyMOL path before this statement and again I failed.
Does anyone know how to call current PyMOL session from python script?
To my knowledge, there is no way to interact with an existing PyMOL session from the Python interpreter. There are a few alternatives:
The existing PyMOL command prompt accepts valid Python and you can run any script directly from the prompt. Perhaps you could execute your script from there instead?
You can start up a new PyMOL session as part of your script. PyMOL's -i flag may be especially helpful- it enables you to work in a headless environment:
-i Disable the internal OpenGL GUI (object list, menus, etc.)
Take a careful look at PyMOL's __init.py__. You'll find the intricacies of PyMOL's threading there. Perhaps you can find something useful to manipulate?
Side note:
Calling print from your script will not make the text appear in the PyMOL session, it will merely write the text to standard output (i.e. it will be printed to your terminal).
The following PyMOL wiki pages may be of help to you:
Running scripts
Launching PyMOL
Launching from a script