I'm writing a Jukebox program that plays media based on key combinations (A1, B2, C3, etc.). Everything works the way I expect with the exception of the "media_player.next()" command.
Let's say you queue up 3 songs. If you hit the "y" key, it skips the song as I'd expect. My issue is that once it gets to the 3rd song, if you hit "y" again, it will circle back to the first song. I don't want that. I want the "y" key to take you forward in the media list...if that is the last song in the media list, don't go to the next song. How do I know if that's the last song in the media list or how do you stop VLC from going back to the beginning?
#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
#
# Set Defaults
#
DefaultUSBPath="/media/pi"
#
# Declare variables
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
Sel_char = None
#
# Find the USB Drive
#
USBDrive = os.path.join(DefaultUSBPath, "USB30FD")
#
# Adding to playlist - Returns directory contents and adds to playlist
#
def addplaylist(track):
list = None
if os.path.isdir(os.path.join(USBDrive, track)):
files = [f for f in os.listdir(os.path.join(USBDrive, track)) if os.path.isfile(os.path.join(USBDrive, track, f))]
for f in files:
if list is None:
list = os.path.join(USBDrive, track, f)
else:
list = list + ";" + os.path.join(USBDrive, track, f)
else:
print ("Error(3) - Selection is invalid")
if list is None:
print ("Error(4) - Selection has no media")
return list
#
# MediaPlayer function
#
def vlc_WhatsPlaying():
pass
def vlc_SongStarted(event):
print("Started")
song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
print(song)
splittrack = song.split("/")
track = splittrack[-2]
print(track)
return
def vlc_SongFinished(event):
print("Finished")
song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
print(song)
splittrack = song.split("/")
track = splittrack[-2]
#media_list.remove_index(0)
#media_player.play_item_at_index(1)
return
#
# Define keyboard actions
#
def on_press(key):
global Action, player
try:
Sel_char = int(key.char)
except:
try:
Sel_char = str(key.char)
Sel_char = Sel_char.upper()
except:
Sel_char = None
if Sel_char == "Z":
return False
elif Sel_char == "Y":
print("Skip")
media_player.next()
elif type(Sel_char) == str:
Action = Sel_char
elif type(Sel_char) == int:
Plist = None
Action = Action + str(Sel_char)
print("Action: " + Action)
Plist = addplaylist(Action)
if Plist is not None:
if ";" in Plist:
print(Plist)
Plist = Plist.split(";")
for p in Plist:
media_list.add_media(p)
else:
media_list.add_media(Plist)
# find section in array and increase the count by one
if not media_player.is_playing():
media_player.play()
else:
print ("Error(4) - Selection has no media")
else:
pass
#
# Setting Up Media Player
#
# creating Instance class object
player = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
media_player = vlc.MediaListPlayer() # creating a media player object
media_list = player.media_list_new() # creating a new media list
media_player.set_media_list(media_list) # setting media list to the media player
new = player.media_player_new() # new media player instance
media_player.set_media_player(new) # setting media player to it
media_events = new.event_manager() # setting event handler
# setting up events
media_events.event_attach(vlc.EventType.MediaPlayerMediaChanged, vlc_SongStarted)
media_events.event_attach(vlc.EventType.MediaPlayerEndReached, vlc_SongFinished)
# Read keyboard input
#
print("Ready...")
with Listener(on_press=on_press) as listener:
listener.join()
#
# Program is shutting down
#
print ("")
print ("Have a nice day!")
print ("")
sys.exit()
As mentioned in my comment the MediaListEndReached doesn't appear to do anything for me, so running with the idea of the list being the easiest way of addressing the issue, the following code tests the list position of the item being played and exits, if the next or previous command attempts to pass beyond the end of the list.
You can achieve the same result simply tracking an index variable.
You may have to adjust the splitting of the mrl to match the entries in your list.
import vlc
import time
## pinched from vlc for keyboard input
import termios
import tty
import sys
mymedia = ["vp.mp3","vp1.mp3","happy.mp3"]
def getch(): # getchar(), getc(stdin) #PYCHOK flake
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
return ch
## end pinched code
def jukebox():
player.play_item_at_index(0)
m = player.get_media_player()
print("Playing - ",m.get_media().get_mrl())
while True:
k = getch()
if k == "n": #Next
media = m.get_media()
if media.get_mrl().rsplit("/",1)[1] == mymedia[-1]: #Next requested but already at the end
break
player.next()
if k == "p": #Previous
media = m.get_media()
if media.get_mrl().rsplit("/",1)[1] == mymedia[0]: #Previous requested but already at the beginning
break
player.previous()
if k == " ": #Pause
player.pause()
if k == "q": #Quit
player.stop()
return True
time.sleep(0.1)
state = player.get_state()
print(state,m.get_media().get_mrl())
print("End of list")
vlc_instance = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
player = vlc_instance.media_list_player_new()
Media = vlc_instance.media_list_new(mymedia)
player.set_media_list(Media)
print("Welcome to Jukebox")
print("Options - space = Play/Pause, n = Next, p = Previous, q = Quit")
print("Media",mymedia)
jukebox()
Related
I'm trying to use a python script to make a connection with my 4x4 keypad on Rastberry (RPi.GPIO).
The code does not work correctly, because the first and second rows does not respond. I'm trying to use pad4pi, but in my case, this not work.
This is the code I'm using in the moment.
(Main Control)
import RPi.GPIO as GPIO
import time
import serial
import Keypad
#import Open_CV
ROWS = 4 # number of rows of the Keypad
COLS = 4 #number of columns of the Keypad
keys = [ '1','2','3','A', #key code
'4','5','6','B',
'7','8','9','C',
'*','0','#','D' ]
rowsPins = [18,22,29,31] #connect to the row pinouts of the keypad
colsPins = [32,33,36,37] #connect to the column pinouts of the keypad
# the pins need to be these, because the others are already in use
# Configure the use of the serial terminal and the baud rate
ser = serial.Serial( #"/dev/ttyS0", 9600)
port='/dev/ttyS0', #Replace ttyS0 with ttyAM0 for Pi1,Pi2,Pi0
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1)
#Configuração inicial dos terminais GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
# call the video method
#video("teste.mp4")
def loop():
keypad = Keypad.Keypad(keys,rowsPins,colsPins,ROWS,COLS) #create Keypad object
keypad.setDebounceTime(50) #set the debounce time
# call the video method
#video('/home/pi/share/teste.mp4')
while(True):
key = keypad.getKey() #obtain the state of keys
if(key != keypad.NULL): #if there is key pressed, print its key code.
print ("You Pressed Key : %c "%(key))
ser.write(str.encode(key))
time.sleep(1)
#ret, frame = cap.read()
#gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#cv2.imshow('frame',gray)
#if cv2.waitKey(1) & 0xFF == ord('q'):
# break
#cap.release()
#cv2.destroyAllWindows()
if __name__ == '__main__': #Program start from here
print ("Program is starting ... ")
try:
loop()
except KeyboardInterrupt: #When 'Ctrl+C' is pressed, exit the program.
GPIO.cleanup()
(keypad functions)
#!/usr/bin/env python3
########################################################################
# Filename : Keypad.py
# Description : The module of matrix keypad
# Author : freenove
# modification: 2016/07/13
########################################################################
import RPi.GPIO as GPIO
import time
#class Key:Define some of the properties of Key
class Key(object):
NO_KEY = '\0'
#Defines the four states of Key
IDLE = 0
PRESSED = 1
HOLD = 2
RELEASED = 3
#define OPEN and CLOSED
OPEN = 0
CLOSED =1
#constructor
def __init__(self):
self.kchar = self.NO_KEY
self.kstate = self.IDLE
self.kcode = -1
self.stateChanged = False
class Keypad(object):
NULL = '\0'
LIST_MAX = 10 #Max number of keys on the active list.
MAPSIZE = 10 #MAPSIZE is the number of rows (times 16 columns)
bitMap = [0]*MAPSIZE
key = [Key()]*LIST_MAX
holdTime = 500 #key hold time
holdTimer = 0
startTime = 0
#Allows custom keymap, pin configuration, and keypad sizes.
def __init__(self,usrKeyMap,row_Pins,col_Pins,num_Rows,num_Cols):
GPIO.setmode(GPIO.BOARD)
self.rowPins = row_Pins
self.colPins = col_Pins
self.numRows = num_Rows
self.numCols = num_Cols
self.keymap = usrKeyMap
self.setDebounceTime(10)
#Returns a single key only. Retained for backwards compatibility.
def getKey(self):
single_key = True
if(self.getKeys() and self.key[0].stateChanged and (self.key[0].kstate == self.key[0].PRESSED)):
return self.key[0].kchar
single_key = False
return self.key[0].NO_KEY
#Populate the key list.
def getKeys(self):
keyActivity = False
#Limit how often the keypad is scanned.
if((time.time() - self.startTime) > self.debounceTime*0.001):
self.scanKeys()
keyActivity = self.updateList()
self.startTime = time.time()
return keyActivity
#Hardware scan ,the result store in bitMap
def scanKeys(self):
#Re-intialize the row pins. Allows sharing these pins with other hardware.
for pin_r in self.rowPins:
GPIO.setup(pin_r,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#bitMap stores ALL the keys that are being pressed.
for pin_c in self.colPins:
GPIO.setup(pin_c,GPIO.OUT)
GPIO.output(pin_c,GPIO.LOW)
for r in self.rowPins: #keypress is active low so invert to high.
self.bitMap[self.rowPins.index(r)] = self.bitWrite(self.bitMap[self.rowPins.index(r)],self.colPins.index(pin_c),not GPIO.input(r))
#Set pin to high impedance input. Effectively ends column pulse.
GPIO.output(pin_c,GPIO.HIGH)
GPIO.setup(pin_c,GPIO.IN)
#Manage the list without rearranging the keys. Returns true if any keys on the list changed state.
def updateList(self):
anyActivity = False
kk = Key()
#Delete any IDLE keys
for i in range(self.LIST_MAX):
if(self.key[i].kstate == kk.IDLE):
self.key[i].kchar = kk.NO_KEY
self.key[i].kcode = -1
self.key[i].stateChanged = False
# Add new keys to empty slots in the key list.
for r in range(self.numRows):
for c in range(self.numCols):
button = self.bitRead(self.bitMap[r],c)
keyChar = self.keymap[r * self.numCols +c]
keyCode = r * self.numCols +c
idx = self.findInList(keyCode)
#Key is already on the list so set its next state.
if(idx > -1):
self.nextKeyState(idx,button)
#Key is NOT on the list so add it.
if((idx == -1) and button):
for i in range(self.LIST_MAX):
if(self.key[i].kchar == kk.NO_KEY): #Find an empty slot or don't add key to list.
self.key[i].kchar = keyChar
self.key[i].kcode = keyCode
self.key[i].kstate = kk.IDLE #Keys NOT on the list have an initial state of IDLE.
self.nextKeyState(i,button)
break #Don't fill all the empty slots with the same key.
#Report if the user changed the state of any key.
for i in range(self.LIST_MAX):
if(self.key[i].stateChanged):
anyActivity = True
return anyActivity
#This function is a state machine but is also used for debouncing the keys.
def nextKeyState(self,idx, button):
self.key[idx].stateChanged = False
kk = Key()
if(self.key[idx].kstate == kk.IDLE):
if(button == kk.CLOSED):
self.transitionTo(idx,kk.PRESSED)
self.holdTimer = time.time() #Get ready for next HOLD state.
elif(self.key[idx].kstate == kk.PRESSED):
if((time.time() - self.holdTimer) > self.holdTime*0.001): #Waiting for a key HOLD...
self.transitionTo(idx,kk.HOLD)
elif(button == kk.OPEN): # or for a key to be RELEASED.
self.transitionTo(idx,kk.RELEASED)
elif(self.key[idx].kstate == kk.HOLD):
if(button == kk.OPEN):
self.transitionTo(idx,kk.RELEASED)
elif(self.key[idx].kstate == kk.RELEASED):
self.transitionTo(idx,kk.IDLE)
def transitionTo(self,idx,nextState):
self.key[idx].kstate = nextState
self.key[idx].stateChanged = True
#Search by code for a key in the list of active keys.
#Returns -1 if not found or the index into the list of active keys.
def findInList(self,keyCode):
for i in range(self.LIST_MAX):
if(self.key[i].kcode == keyCode):
return i
return -1
#set Debounce Time, The defaul29t is 50ms
def setDebounceTime(self,ms):
self.debounceTime = ms
#set HoldTime,The default is 500ms
def setHoldTime(self,ms):
self.holdTime = ms
#
def isPressed(self, keyChar):
for i in range(self.LIST_MAX):
if(self.key[i].kchar == keyChar):
if(self.key[i].kstate == self.self.key[i].PRESSED and self.key[i].stateChanged):
return True
return False
#
def waitForKey(self):
kk = Key()
waitKey = kk.NO_KEY
while(waitKey == kk.NO_KEY):
waitKey = self.getKey()
return waitKey
def getState(self):
return self.key[0].kstate
#
def keyStateChanged(self):
return self.key[0].stateChanged
def bitWrite(self,x,n,b):
if(b):
x |= (1<<n)
else:
x &=(~(1<<n))
return x
def bitRead(self,x,n):
if((x>>n)&1 == 1):
return True
else:
return False
Okay so I'm using pyinstaller to create an exe file for my python project to run, but when I run it, the exe file will open up my menu, and it will work perfectly fine, but when I select an option, it will clear the screen and then close the program. The program works perfectly well when run from command line. Below is the menu that I using pyinstaller on.
from pick import pick
import subprocess
def select_difficulty():
title = "Welcome to LowKeyBored's implementation of Typing Test (Rev 0)!"+'\nSelect difficulty'
options = ['Easy','Medium','Hard']
option, index = pick(options, title)
return option
def set_difficulty():
diff_args = ['-v']
difficulty = select_difficulty()
if difficulty == 'Easy':
diff_args.append('easy')
elif difficulty == 'Medium':
diff_args.append('medium')
else:
diff_args.append('hard')
return diff_args
def main():
diff_args = set_difficulty()
launch_args = ['python3','runner.py']+diff_args
subprocess.run(launch_args)
main()
runner .py
import typing_test
typing_test.main()
typingtest.py
"""
Copyright (c) 2019 Emil Lynegaard
Distributed under the MIT software license, see the
accompanying LICENSE.md or https://opensource.org/licenses/MIT
Minimal 10fastfingers like typing game for Python2/3 with ncurses.
Supports vocab files as arguments, as well as adjustable
word length, game time and word frequency (if using sorted vocab).
"""
import argparse
import time
import random
import curses
import textwrap
import os
# Robust path to default vocabulary, which is based on word frequency
# from CNN and DailyMail articles.
VOCAB_PATH = os.path.join(os.path.dirname(__file__), "data", "vocab")
# Used for WPM calculation
CHARS_PER_WORD = 5
# Amount of words to store, for showing several future words
# Should generally be equal to at least two lines worth of words
QUEUE_SIZE = 30
# Maximum amount of characters to be displayed in a single row
MAX_WIDTH = 80
# pylint: disable=too-many-instance-attributes
class Game:
"""
Class encapsulating the Game.
Includes game stats, input management, game display.
"""
CORRECT_COLOR = 1
INCORRECT_COLOR = 2
def __init__(self, args):
self.word_generator = self._word_generator(args)
self.game_time = args.game_time
self.next_words = [self._get_word() for _ in range(QUEUE_SIZE)]
self.typed = []
self.correct = []
self.incorrect = []
self.input = ""
self.display = args.display
# if using 10ff display, we keep track of extra things
if self.display == "10ff":
self.offset = 0
self.current_line = []
self.next_line = []
#staticmethod
def _word_generator(args):
words = []
for line in open(os.path.join(os.path.dirname(__file__), "data",args.vocab)):
word = line.strip()
if args.min_length <= len(word) <= args.max_length:
words.append(word)
if len(words) >= args.words:
break
if args.mode == "word":
while True:
yield random.choice(words)
else:
while True:
yield from words
def calculate_cpm(self, time_played):
"""Calculate CPM given time_played in seconds"""
if time_played == 0:
return 0
correct_chars = len(" ".join(self.correct))
cpm = 60 / time_played * correct_chars
cpm = int(round(cpm))
return cpm
def calculate_wpm(self, time_played):
"""Calculate WPM given time_played in seconds"""
cpm = self.calculate_cpm(time_played)
wpm = cpm // CHARS_PER_WORD
return wpm
def _get_word(self):
return next(self.word_generator)
def _finish_word_event(self):
target = self.next_words.pop(0)
self.typed.append(self.input)
if self.input == target:
self.correct.append(target)
else:
self.incorrect.append(target)
if self.display == "10ff":
self.offset += 1
self.next_words.append(self._get_word())
self.input = ""
#staticmethod
def _get_line(words, max_chars):
line = []
chars = 0
for word in words:
length = len(word)
# use +1 to account for added whitespace
if chars + length + 1 > max_chars:
break
line.append(word)
chars += length + 1
return line
def _progressive_display(self, stdscr, time_left):
_height, width = stdscr.getmaxyx()
width = min(width, MAX_WIDTH)
stdscr.clear()
wpm = self.calculate_wpm(self.game_time - time_left)
stdscr.addstr("Time left: {:d}, WPM: {:d}\n".format(time_left, wpm)+", Difficulty Level: "+self.difficulty_level+"\n")
line = self._get_line(self.next_words, width)
target = " ".join(line)
for idx, char in enumerate(self.input):
target_char = target[idx]
if target_char == char:
stdscr.addstr(char, curses.color_pair(self.CORRECT_COLOR))
else:
stdscr.addstr(target_char, curses.color_pair(self.INCORRECT_COLOR))
stdscr.addstr(target[len(self.input) : width - 1])
stdscr.addstr("\n" + self.input, curses.A_UNDERLINE)
stdscr.refresh()
def _10ff_display(self, stdscr, time_left):
_height, width = stdscr.getmaxyx()
width = min(width, MAX_WIDTH)
stdscr.clear()
wpm = self.calculate_wpm(self.game_time - time_left)
# stdscr.addstr("Time left: {:d}, WPM: {:d}".format(time_left, wpm)+", Difficulty Level: "+self.difficulty_level+"\n")
stdscr.addstr("Time left: {:d}, WPM: {:d}".format(time_left, wpm)+"\n")
# sets up initial lines
if not self.current_line:
self.current_line = self._get_line(self.next_words, width)
cur_len = len(self.current_line)
self.next_line = self._get_line(self.next_words[cur_len:], width)
# if we finished the current line
if self.offset >= len(self.current_line):
self.current_line = self.next_line
cur_len = len(self.current_line)
self.next_line = self._get_line(self.next_words[cur_len:], width)
self.offset = 0
# color the words already typed on current line
for i in range(self.offset):
target = self.current_line[i]
actual = self.typed[-(self.offset - i)]
if actual == target:
stdscr.addstr(target, curses.color_pair(self.CORRECT_COLOR))
else:
stdscr.addstr(target, curses.color_pair(self.INCORRECT_COLOR))
stdscr.addstr(" ")
stdscr.addstr(" ".join(self.current_line[self.offset :]))
stdscr.addstr("\n" + " ".join(self.next_line))
stdscr.addstr("\n" + self.input, curses.A_UNDERLINE)
stdscr.refresh()
def _update_display(self, stdscr, time_left):
if self.display == "progressive":
self._progressive_display(stdscr, time_left)
elif self.display == "10ff":
self._10ff_display(stdscr, time_left)
def _handle_key(self, key):
char = curses.keyname(key).decode()
if char == "^R":
self.restart()
if key in (curses.KEY_BACKSPACE, 127):
self.input = self.input[:-1]
elif chr(key) == " ":
self._finish_word_event()
else:
self.input += chr(key)
#staticmethod
def _setup_ncurses(stdscr):
# hide cursor
curses.curs_set(0)
# setup colors for printing text to screen
curses.use_default_colors()
curses.init_pair(Game.CORRECT_COLOR, curses.COLOR_GREEN, 0)
curses.init_pair(Game.INCORRECT_COLOR, curses.COLOR_RED, 0)
# don't wait for user input when calling getch()/getkey()
stdscr.nodelay(True)
# allow 100ms sleep on getch()/getkey() avoiding busy-wait
# early returns when key is pressed, meaning no input delay
stdscr.timeout(100)
def _game_loop(self, stdscr):
self._setup_ncurses(stdscr)
self._update_display(stdscr, self.game_time)
started = False
start = time.time()
time_left = self.game_time
while time_left > 0:
if not started:
start = time.time()
key = stdscr.getch()
new_time_left = int(round(self.game_time - (time.time() - start)))
if key == -1:
# only update display when necessary
if time_left != new_time_left:
time_left = new_time_left
self._update_display(stdscr, time_left)
continue
time_left = new_time_left
started = True
self._handle_key(key)
self._update_display(stdscr, time_left)
def print_stats(self):
"""Print ACC/CPM/WPM to console"""
correct = len(self.correct)
total = correct + len(self.incorrect)
accuracy = correct / total * 100
print("ACC: {:.2f}%".format(accuracy))
cpm = self.calculate_cpm(self.game_time)
print("CPM: {:d}".format(cpm))
wpm = self.calculate_wpm(self.game_time)
print("WPM: {:d}".format(wpm))
def restart(self):
"""
Reset the Game class, effective starting a new game
with new words, but based on same configuration.
"""
self.input = ""
self.correct = []
self.incorrect = []
self.typed = []
self.next_words = [self._get_word() for _ in range(QUEUE_SIZE)]
if self.display == "10ff":
self.offset = 0
self.current_line = []
self.next_line = []
self.play()
def play(self):
"""Start typing game and print results to terminal"""
curses.wrapper(self._game_loop)
self.print_stats()
def main():
"""Parse arguments and start game based thereof"""
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter,
description=textwrap.dedent(
"""\
Start a minimal 10fastfingers-like typing game on the command line.
Keybinds:
CTRL+R: restart
CTRL+C: exit
"""
),
)
## replace this with the select-difficulty + language
parser.add_argument(
"-v",
"--vocab",
type=str,
metavar="vocab-file-path",
default=VOCAB_PATH,
help="path to newline separated vocab file",
)
parser.add_argument(
"-t",
"--game_time",
type=int,
metavar="gametime-seconds",
default=60,
help="duration in seconds of the typing game",
)
parser.add_argument(
"-min",
"--min_length",
type=int,
metavar="min-word-length",
default=1,
help="minimum word length",
)
parser.add_argument(
"-max",
"--max_length",
type=int,
metavar="max-word-length",
default=100,
help="maximum word length",
)
parser.add_argument(
"-w",
"--words",
type=int,
metavar="words-to-read",
default=200,
help="the amount of words to read from vocab - higher increases difficulty",
)
parser.add_argument(
"-a",
"--advanced",
action="store_const",
const=1000,
dest="words",
help="use 1000 most common words (corresponds to 10ff advanced mode)",
)
parser.add_argument(
"-d",
"--display",
type=str,
metavar="display",
default="10ff",
help="how to display words to type '10ff' or 'progressive'",
)
parser.add_argument(
"-m",
"--mode",
type=str,
metavar="mode-selection",
default="word",
help="selecting which mode you wish to play the game in",
)
args = parser.parse_args()
game = Game(args)
try:
game.play()
except KeyboardInterrupt:
pass
If anyone can give me advice on how to fix this that would help. Not sure if its the way I used pyinstaller or if its a problem with how I run a script within the first python file, and dependencies might not be implemented properly. Running the file give me the following:
This was simply a problem with directories. Pyinstaller put the executable file in it's own directory, where it couldn't import from the rest of my python files. I fixed it by dragging the executable into the directory with the rest of my python scripts. This is more of a temporary solution, as the executable has to be in the same directory as the other python files until I fix the import statements.
I just made a little program to make some plots with tkinter in python.
And I'm trying to make the app to create png file not overlapping the previous one.
So like, if it exists, rename it as ~ (1).png kinda thing.
But when I run os.path.isfile or os.path.exists, the app just freezes. Like, endless hourglasses turning and saying not responding, you know.
So, this is the function I binded with the button.
def get_information_S():
global nation_list, checked_list, output, year_menu, auto_flag, df
year = year_menu.get()
checked_list.sort()
nations = []
if auto_flag == 0:
for n in range(len(nation_list)):
nations.append(nation_list[n][0].get())
else:
pass
if len(year) == 0:
output_log("연도를 선택해주세요.\n")
elif len(checked_list) == 0:
output_log("hs코드를 선택해주세요.\n")
else:
output_log("\n\n분석 연도 : "+str(year)+"\n분석 품목 : "+str(checked_list)+"\n분석 국가 : "+str(nations)+"\n분석을 실시했습니다.\n")
for x in range(len(checked_list)):
os.makedirs("result", exist_ok=True)
os.makedirs("result\\single", exist_ok=True)
os.makedirs("result\\single\\hs_"+str(checked_list[x]),exist_ok = True)
df_test = df[df.hs6==int(checked_list[x])]
df_test = df_test[df_test.year==int(year)]
file_loc = "result\\single\\hs_"+str(checked_list[x])+"\\hs_"+str(checked_list[x])+"_"+str(year)+'.png'
f = -1
while True:
f+= 1
if os.path.isfile(file_loc) == True:
if f == 0:
file_loc = file_loc.replace('_.png','_('+str(f)+').png')
else:
file_loc = file_loc.replace('('+str(f-1)+')','('+str(f)+')')
continue
else:
break
plain_graph(df_test, file_loc, checked_list[x], nations)
Well, it's my first time dealing with GUI.
Is there a way I can use os.path.isfile or os.path.exists? Or any walkaround?
Thank you!
The initial value of file_loc is something like "result\\single\\hs_xxxx_2021.png" (assume year is 2021), then in the first iteration of the while loop, if f == 0 will be evaluated as True and so
file_loc = file_loc.replace('_.png','_('+str(f)+').png')
will be executed, but nothing will be replaced as _.png is not found in file_loc and so file_loc is kept as initial value and continue line will proceed to next iteration. As the file_loc does not change and f is increased, the else part
file_loc = file_loc.replace('('+str(f-1)+')','('+str(f)+')')
will be executed but again nothing is replaced as the search pattern is not found in file_loc.
Then same result happens for every iteration followed and make the while loop an infinite loop.
So the mentioned line should be changed to:
file_loc = file_loc.replace('.png','('+str(f)+').png')
I have a folder in which there are some video files. I want to extract frames from the videos but only those videos should be processed whose names are not present in the csv. It should check for the present video file names in the csv before processing the videos
def extractFrames(m):
global vid_name
vid_files=glob(m)
print(vid_files)
complete_videos = get_completed_videos()
print(complete_videos)
new_vid_files = [x for x in vid_files if get_vid_name(x) not in complete_videos]
for vid in new_vid_files:
print("path of video========>>>>.",vid)
v1=os.path.basename(vid)
try:
vid_name = get_vid_name(vid)
vidcap = cv2.VideoCapture(vid)
except cv2.error as e:
print(e)
except:
print('error')
#condition
fsize=os.stat(vid)
print('=============size of video ===================:' , fsize.st_size)
try:
if (fsize.st_size > 1000):
fps = vidcap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frameCount = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = frameCount/fps
minutes = int(duration/60)
print('fps = ' + str(fps))
print('number of frames = ' + str(frameCount))
print('duration (S) = ' + str(duration))
if (duration > 1):
success,image = vidcap.read()
count=0
success=True
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
success,image = vidcap.read()
if count % 10 == 0 or count ==0:
target_non_target(img_name, image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
except:
print("error")
print('finished processing video ',vid)
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv', 'a') as csv_file:
fieldnames = ['Video_Name','Process']
file_is_empty = os.stat("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv').st_size == 0
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
if file_is_empty:
writer.writeheader()
writer.writerow({'Video_Name':vid_name,'Process':'done'})
def get_vid_name(vid):
return os.path.splitext(os.path.basename(vid))[0]
def get_completed_videos():
completed_videos = []
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\video_info.csv") as csv_file:
for row in csv.reader(csv_file):
for col in range(0,len(row)):
try:
completed_videos.append(row[col])
except Exception as e:
print(str(e))
print(completed_videos[0])
return completed_videos
Suppose there are 3 videos in a folder. Code is successfully run for those 3 videos and their names are written in the csv. Now if i paste video number 4 in the folder then it should process only the 4th video after checking for the video names present in the csv. Currently it is repeatedly processing all the video files everytime the script is run.
First off, inside the for loop
v1=os.path.basename(vid_files[v_f])
Should be
v1=os.path.basename(new_vid_files[v_f])
Since you are looping over the new_vid_files range. Using those indices on the original list will give you unexpected items. Better yet, you can directly use a for-each loop (since you don't seem to be using v_f for anything other than list access) as follows:
for vid in new_vid_files:
And this vid would replace all instances of new_vid_files[v_f].
Next, you are using vid_name to write to the csv, so you need to perform the same operation for each item from vid_files before matching against complete_videos while creating the new_vid_files list.
If you create a method for getting the video name as follows:
def get_vid_name(vid_file):
return os.path.splitext(os.path.basename(vid_file))[0]
Then you can change the list comprehension to be
new_vid_files = [x for x in vid_files if get_vid_name(x) not in complete_videos]
Edit: As mentioned in the comments to the other answer, the output for complete_videos indicates it isn't being parsed properly. It is appending both the column headers and other unneeded columns. This code will work despite that, but it needs to be fixed. I am not solving it because it is a relatively simple change, and I want the OP to understand what they're doing wrong.
def extractFrames(m):
global vid_name
vid_files=glob(m)
print(vid_files)
complete_videos = get_completed_videos()
new_vid_files = [x for x in vid_files if get_vid_name(x) not in complete_videos]
for vid in new_vid_files:
print("path of video========>>>>.",vid)
v1=os.path.basename(vid)
try:
vid_name = get_vid_name(vid)
vidcap = cv2.VideoCapture(vid)
except cv2.error as e:
print(e)
except:
print('error')
#condition
fsize=os.stat(vid)
print('=============size of video ===================:' , fsize.st_size)
try:
if (fsize.st_size > 1000):
fps = vidcap.get(cv2.CAP_PROP_FPS) # OpenCV2 version 2 used "CV_CAP_PROP_FPS"
frameCount = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
duration = frameCount/fps
minutes = int(duration/60)
print('fps = ' + str(fps))
print('number of frames = ' + str(frameCount))
print('duration (S) = ' + str(duration))
if (duration > 1):
success,image = vidcap.read()
count=0
success=True
while success:
img_name = vid_name + '_f' + str(count) + ".jpg"
success,image = vidcap.read()
if count % 10 == 0 or count ==0:
target_non_target(img_name, image)
count+=1
vidcap.release()
cv2.destroyAllWindows()
except:
print("error")
print('finished processing video ',vid)
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv', 'a') as csv_file:
fieldnames = ['Video_Name','Process']
file_is_empty = os.stat("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\"+'video_info.csv').st_size == 0
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
if file_is_empty:
writer.writeheader()
writer.writerow({'Video_Name':vid,'Process':'done'})
def get_vid_name(vid):
return os.path.splitext(os.path.basename(vid))[0]
def get_completed_videos():
completed_videos = []
with open("C:\\multi_cat_3\\models\\research\\object_detection\\my_imgs\\video_info.csv") as csv_file:
for row in csv.reader(csv_file):
for col in range(0,len(row)):
try:
completed_videos.append(row[col])
except Exception as e:
print(str(e))
print(completed_videos[0])
return completed_videos
Im trying to simulate two machines working, and failing at random times. When they fail they call assistance. These two machines is part of bigger system of different machines, which needs to know when its neighbor has failed to do its job.
So far, I have made the simulate of the two machines, but I cant figure out how to send messages to their neighbors without each machine needing to know the whole system?
This is what I have so far:
import simpy
import random
random_seed=42
MTTF = 3500
break_mean = 1 / MTTF
sim_time = 4 * 7*24*60 # 4 weeks 24/7
num_machines = 2
rep_time = 30
tpp = 20 #20 minutes to make each part
neighbour = 3 #How many should it send to?
#Creating a class called messaging which is an object.
class messaging(object):
#DEfing the initilizing function, and initilize self, Environment, and capacity which is set to infinity, by a simpy core-function.
def __init__(self, env, capacity=simpy.core.Infinity):
self.env = env
self.capacity = capacity
self.pipes = []
#Making a function which work on everything that is a part of the message. With name Put.
def put(self, value):
if not self.pipes: #How to get this error?
raise runtime_error('There are no output pipes.')
#Create a variable, events, store to it pipe values
events = broken_machine()
return self.env.all_of(events)
def get_output_conn(self):
#Set the capacity of pipe variable to store infinity.
pipe = simpy.Store(self.env, capacity=self.capacity)
#to each pipes, add(or append) pipe
self.pipes.append(pipe)
return pipe
def mesg_generator(number, env, out_pipe):
msg = ('Failed')
def message_reciever(name, env, in_pipe):
while True:
msg = yield in_pipe.get()
print("%s received message: %s" % (number, msg[1]))
def time_per_part():
return tpp
def ttf():
return random.expovariate(break_mean)
class Machine(object):
def __init__(self, env, number, repair):
#self.arg = arg
self.env = env
self.number = number
self.parts_made = 0
self.times_broken = 0
self.broken = False
self.process = env.process(self.working(repair))
env.process(self.broken_machine())
def working(self, repair):
while True:
work = time_per_part()
while work:
try:
begin = self.env.now
yield self.env.timeout(work)
work = 0
except simpy.Interrupt:
self.broken = True
work -= self.env.now - begin
with repair.request(priority = 1) as req:
yield req
yield self.env.timeout(rep_time)
self.times_broken +=1
yield message_reciever()
#print('Machine down')
self.broken = False #Machine fixed again
self.parts_made +=1
def broken_machine(self):
while True:
yield self.env.timeout(ttf())
if not self.broken:
self.process.interrupt()
def other_jobs(env, repair):
while True:
work = tpp
while work:
with repair.request(priority=2) as req:
yield req
try:
begin = env.now
yield env.timeout(work)
work = 0
except simpy.Interrupt:
work -= env.now - begin
print("This simulates machines 3 and 4 doing the same tasks.")
random.seed(random_seed)
env = simpy.Environment()
pipe = simpy.Store(env)
bc_pipe = messaging(env)
repair = simpy.PreemptiveResource(env, capacity = 1)
machines = [Machine(env, 'Machine %d' % i, repair)
for i in range(num_machines)]
env.process(other_jobs(env, repair))
env.run(until=sim_time)
#Show how many times each machine failed:
for machine in machines:
print("%s broke down %d times" %(machine.number, machine.times_broken))