Im trying to print a gif in my homework game if someone wins or loses, and for that I have this code:
import shutil
import pyglet
import requests
import os
def gif():
url = 'https://tenor.com/view/no-oh-no-nope-nah-not-really-gif-15162749.gif'
filename = url.split('/')[-1]
with open(filename, 'wb') as out_file:
out_file.write(requests.get(url).content)
os.rename('no-oh-no-nope-nah-not-really-gif-15162749.gif', 'michaelscott1.gif')
animation = pyglet.image.load_animation('michaelscott1.gif')
animSprite = pyglet.sprite.Sprite(animation)
w = animSprite.width
h = animSprite.height
window = pyglet.window.Window(width=w, height=h)
#window.event
def on_draw():
window.clear()
animSprite.draw()
pyglet.app.run()
gif()
If I run it the program it shows the gif, and when I close it, the program finishes with exit code 0.
If I put a print statement after it, it shows the gif, prints the print and then finishes with exit code 0.
But if I try to make an input statement after the gif
input('>')
The python window showing the gif crashes. And when I force close it, the script quits, and I get this return statement:
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)
What is the solution to this?
Assuming you switch to Python3 (which you should), things might start to work a little bit better.
Some improvements if nothing else to the code, would be to not store the image on disk unless you really need to.
You can circumvent this by using io.BytesIO and load the image from within memory:
import pyglet
import os
import urllib.request, io
def url_to_sprite(url):
with urllib.request.urlopen(url) as response:
image_data = response.read()
image = pyglet.image.load_animation(os.path.basename(url), file=io.BytesIO(image_data))
return pyglet.sprite.Sprite(image)
animSprite = url_to_sprite('https://media.giphy.com/media/13gvXfEVlxQjDO/giphy.gif')
input('>')
window = pyglet.window.Window(width=animSprite.width, height=animSprite.height)
#window.event
def on_draw():
window.clear()
animSprite.draw()
pyglet.app.run()
I can't reproduce any errors with this code. And nothing crashes when using the input.
The program will however not render anything until after the input is completed.
Related
I have made a script that checks 100 times whether an image can be detected. He clicks it if it is seen in the last if statement. But a few things are going wrong here.
1: He doesn't right-click what I do.
2: after clicking my script closes immediately!
What did I do wrong? and how do I fix this?
This is my code
import os
import pyautogui
import time
import subprocess
def openprogram():
#opens program
subprocess.call(["cmd", "/c", "start", "/max", "D:\FarmHelper3.exe"])
def inloggen():
#searches for image 100 times to login
for _ in range(100):
time.sleep(1)
coords = pyautogui.locateOnScreen('images/login.png')
#if he has not found the photo within the program
if coords == None:
print ("Geen login gevonden")
#if the picture is found
if coords != None:
print ("Login gevonden")
pyautogui.rightClick(coords)
openprogram()
inloggen()
I am fairly new to Python and Computer Vision but I've managed to setup a basic script to open my CCTV camera's at home. It works great but I have a slight issue is is that it loops over each camera one after the other, so instead of the camera image updating every second, it updates around every 5 seconds - the time it takes to complete a loop.
What I want is to be able to use multiprocessing / multi threading so that when I call the function for each of my cameras it open ins a new pool, running parallel to each other, therefore updating each camera every second.
As you can see in the below code I call each of the cameras using the same function, but with different argurments. I've read up on Process and have tried a few variations but I don't seem to be able to get it working.
I'm sure its a simple one and it would be great if someone could point me in the right direction.
Here's the code:
# import libraries
from threading import Thread
import imutils
import cv2, time
import argparse
import numpy as np
import datetime
from imutils.video import WebcamVideoStream
from multiprocessing import Process
stream = WebcamVideoStream('rtsp://mylink1./' ).start() # To open any valid video file stream/network stream. In this case 'test.mp4' file.
stream2 = WebcamVideoStream('rtsp://mylink2./' ).start()
stream3 = WebcamVideoStream('rtsp://mylink3./' ).start()
stream4 = WebcamVideoStream('rtsp://mylink4./' ).start()
stream5 = WebcamVideoStream('rtsp://mylink5./' ).start()
def checkimage(stream,camname):
global lastmessage
try:
frame = stream.read()
(h, w) = frame.shape[:2]
cv2.imshow(camname, frame)
print('[INFO]Checked ' + str(camname) + ' at ' + datetime.datetime.now().strftime("%H:%M:%S") + '...')
except AttributeError:
pass
# infinite loop
while True:
checkimage(stream,"Back Door Camera")
checkimage(stream2,"Conservatory Camera")
checkimage(stream3,"Front Door Camera")
checkimage(stream4,"Garage Camera")
checkimage(stream5,"Shed Camera")
key = cv2.waitKey(1) & 0xFF
# check for 'q' key-press
if key == ord("q"):
if 'q' key-pressed break out
break
cv2.destroyAllWindows()
# close output window
stream.stop()
# safely close video stream.
Thanks in advance!
Chris
I am trying to write a version of the interactive interpreter which has syntax highlighting.
Here's what I have so far which works reasonably well (uses blessings and pygments modules)...
import code
import readline
import threading
import blessings
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers import PythonLexer
def check_line():
global current_line
try:
while True:
line = readline.get_line_buffer()
if line != current_line:
current_line = line
do_colour()
except:
pass
def do_colour():
global terminal
raw_line = readline.get_line_buffer()
line = highlight(raw_line, lexer, formatter)[:-1]
with terminal.location(x = 4):
print line,
readline.redisplay()
current_line = ''
terminal = blessings.Terminal()
lexer = PythonLexer()
formatter = TerminalFormatter()
console = code.InteractiveConsole()
colour_thread = threading.Thread(target=check_line)
colour_thread.setDaemon(True)
colour_thread.start()
console.interact('')
It does colour the lines as you type them...
The problems are;
This uses a separate thread to busy-check for changes in the line (think this might be using a whole core)
If you move cursor back through a line, then move it back to the right, the terminal redraws the character that was just unselected, and it does it in white
What I really want is a callback/hook for when the cursor moves or the line buffer changes - are either of these things possible? Can I put stdin into byte-by-byte mode, then somehow pass the bytes to an internal buffered version of raw_input, and also fire the callback?
P.S it also doesn't deal with multi-line strings ("""like this""") at the moment, but this isn't a very difficult fix.
Edit:
Ok, I have kind of got there, here's the latest code...
import code, ctypes, readline, blessings, signal, threading
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers import PythonLexer
def slight_delay():
threading.Timer(0.001, draw).start()
return 0
def draw():
raw_line = readline.get_line_buffer()
line = highlight(raw_line, lexer, formatter)[:-1]
with lock:
with terminal.location(x = 4):
print line,
readline.redisplay()
def keyboard_interrupt(c, frame): # Ctrl-C throws in C code otherwise
pass
callback = ctypes.PYFUNCTYPE(ctypes.c_int)(slight_delay)
hook_ptr = ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
hook_ptr.value = ctypes.cast(callback, ctypes.c_void_p).value
signal.signal(signal.SIGINT, keyboard_interrupt)
terminal = blessings.Terminal()
lexer = PythonLexer()
formatter = TerminalFormatter()
console = code.InteractiveConsole()
lock = threading.Lock()
console.interact('')
The thing I was looking for was PyOS_InputHook which is called
On every key press
Every 0.1 seconds
So this means I could ditch the busy watch thread and means I don't use (almost) any CPU.
The final problem was that the input hook is called immediately on key press; before the input has been read from stdin and (for printable chars) attached to the line buffer. The result was that there was a 0.1 second delay to colouring the most recent character.
I solved this in a bit a of a hacky way by doing the drawing in a thread on a 0.001 second delay.
I'm making a slideshow app with that oh-so-naught-ies pan and zoom effect. I'm using pygame.
The main display is therefore realtime 30fps+, and I don't want it stuttering when it has to load a new image - this takes it over 1/30th of a second.
So I wanted to use some parallel process to prepare the images and feed the main process with these objects, which are instances of a class.
I've tried with threading and with multiprocess. Threading 'works' but it's still jumpy (I blame python) - the whole thing slows down when the thread is busy! So the code ran but it didn't meet the goal of allowing a continually smooth display.
But multiprocess segfaults (pygame parachute) as soon as I call a method on the received prepared image from the main process. I've tried pipe and queue communications - both result in the same problem. The method runs up until it does a call to
sized = pygame.transform.scale(self.image, newsize )
Then there's the segfault. This class does not have any dependencies from the main process.
Does pygame just not like multiprocessing? Is there another way that is compatible? Is there a way to 'nice' secondary threads that might stop the threading method performing?
Any help greatly appreciated. Happy to post more code, just ask in comments, but didn't want to dump a big listing here unless needed.
Thanks in advance!
EDIT
This is as short as I could make it. You need to provide three paths to jpeg files in the constructor at the bottom.
#!/usr/bin/env python2
import pygame
import sys
import time
import re
import os
import pickle
from random import randrange, shuffle
from multiprocessing import Process, Pipe
import Queue
class Img:
"""The image objects I need to pass around"""
def __init__(self, filename=None):
image = pygame.image.load(filename).convert()
self.image = pygame.transform.scale(image, (640,480))
def getSurface(self):
"""Get a surface, blit our image onto it in right place."""
surface = pygame.Surface((640,480))
# xxx this next command fails
sized = pygame.transform.scale(self.image, (640,480))
surface.blit(sized, (0,0))
return surface
class Floaty:
"""demo"""
def __init__(self, fileList):
self.fileList = fileList
pygame.init()
self.screen = pygame.display.set_mode((640,480))
# open the first image to get it going
self.img = Img(self.fileList.pop())
# Set up parallel process for opening images
self.parent_conn, child_conn = Pipe()
self.feeder = Process(target=asyncPrep, args=(child_conn,))
self.feeder.start()
def draw(self):
"""draw the image"""
# collect image ready-prepared by other process
if self.parent_conn.poll():
self.img = self.parent_conn.recv()
print ("received ", self.img)
# request new image
self.parent_conn.send(self.fileList.pop())
self.screen.blit(self.img.getSurface(), (0, 0))
pygame.display.flip()
def asyncPrep(conn):
"""load up the files"""
while True:
if conn.poll(1):
filename = conn.recv()
print ("doing ", filename)
img = Img(filename)
conn.send(img)
if __name__ == '__main__':
fileList = ['/path/to/a.jpg', 'path/to/b.jpg', 'path/to/c.jpg']
f = Floaty(fileList)
clock = pygame.time.Clock()
while 1:
f.draw()
clock.tick(4);
When I run this (Python 2.7.6) I get:
('doing ', '/path/to/a.jpg')
('received ', <__main__.Img instance at 0x7f2dbde2ce60>)
('doing ', '/path/to/b.jpg')
Fatal Python error: (pygame parachute) Segmentation Fault
zsh: abort (core dumped)
I solved this using multiprocessing by making the Img class load the image into a string buffer, stored in a property, then adding a postReceive method which loads it into a surface stored in the image property.
The postReceive method is called by the parent process after receiving the Img object from the child.
Therefore the object created by the child is not bound to anything pygame-y.
self.imageBuffer = pygame.image.tostring(
pygame.transform.scale(image, (640,480)),
'RGB')
Then, the new method in Img is simply:
def: postReceive(self):
self.image = pygame.image.frombuffer( self.imagebuffer, 'RGB' )
Add a call to this here:
# collect image ready-prepared by other process
if self.parent_conn.poll():
self.img = self.parent_conn.recv().postReceive()
print ("received ", self.img)
I am building application with interactive console interface (line htop, atop utilities) using urwid library, so my trouble is: as interface takes all the space in console window - I could not see python's errors, I tried to do that:
import sys
f = open("test_err", "w")
original_stderr = sys.stderr
sys.stderr = f
print a #a is undefined
sys.stderr = original_stderr
f.close()
It works when I dont use urwid, but not when I use it...
you could try redirecting errors to a file. after each time you run the program, you will need to refresh the file. most editors let you easily do this by pushing f5
def main():
#your code here
print someError #raises an error
try: #run main function
main()
except BaseException as err: #catch all errors
with open('errors.txt','a') as errors: #open a file to write the errors to
errors.write(err.message+'\n')#write the error
change the 'a' to 'w' in the open function if you only want to see one error in the file at a time (instead of having multiple error over a long period of time in one file).
if you want to see the error right when it happens, you can make the error catcher open a window that has the error on it.
def main():
#your code here
print someErr
try: #run main function
main()
except BaseException as err: #catch all errors
import Tkinter as tk #imports the ui module
root = tk.Tk() #creates the root of the window
#creates the text and attaches it to the root
window = tk.Label(root, text=err.message)
window.pack()
#runs the window
root.mainloop()
if you want to build your own window to catch errors, you can learn about Tkinter here. (it is built into python, you don't have to install anything)
Here's what I came up with. I'm taking advantage of unicode-rxvt (urxvt) feature to be passed in a file descriptor. Of course this means you need to be developing this in an X environment, and not a console.
from __future__ import print_function
import os
from datetime import datetime
_debugfile = None
def _close_debug(fo):
fo.close()
def DEBUG(*obj):
"""Open a terminal emulator and write messages to it for debugging."""
global _debugfile
if _debugfile is None:
import atexit
masterfd, slavefd = os.openpty()
pid = os.fork()
if pid: # parent
os.close(masterfd)
_debugfile = os.fdopen(slavefd, "w+", 0)
atexit.register(_close_debug, _debugfile)
else: # child
os.close(slavefd)
os.execlp("urxvt", "urxvt", "-pty-fd", str(masterfd))
print(datetime.now(), ":", ", ".join(map(repr, obj)), file=_debugfile)
This will open a new terminal window automatically when you call DEBUG for the first time and close it at exit. Then any messages passed to it are shown in this new window. This is your "debug window". So your main app works normally, without cluttering it up with messages, but you can still see debug output in this new terminal.