So I was developing a GUI with tkinter and I have realised that I have so many nested functions in my code that I think it is not a good practice. However, I think my code will not work without using them.
My code:
def convertFiles():
files = []
cname = my_lb.curselection()
for i in cname:
op = my_lb.get(i)
files.append(op)
if files == []:
messagebox.showinfo('', 'Please choose a file')
else:
pass_files = []
decrypted_data = []
if messagebox.askquestion('Convert', 'Are you sure to convert your file(s)?'):
kill_command = ["gpgconf", "--kill", "gpg-agent"]
kill_out = subprocess.check_output(kill_command, universal_newlines=False)
disable_button()
for val in files:
pass_files.append(f'{pwd}/.password-store/{val}')
newWindow = tk.Toplevel(root)
newWindow.title("Passphrase for Asymmetric Decryption")
newWindow.geometry("400x150")
newWindow.resizable(False,False)
tk.Label(newWindow,text ="Please put your passphrase for decryption.").place(x=0,y=0)
passp_entry = tk.Entry(newWindow)
passp_entry.place(x=0,y=30)
def get_entry():
passp = passp_entry.get()
if passp:
for x in range(0, len(pass_files)):
command1 = ["gpg", "-d", "--quiet", "--yes", "--pinentry-mode=loopback", f"--passphrase={passp}", f'{pass_files[x]}.gpg']
out = subprocess.check_output(command1, universal_newlines=False)
decrypted_data.append(out)
print('Asymmetric decryption is complete.')
newWindow.destroy()
add_button = tk.Button(newWindow, text='Enter', command=get_entry)
add_button.place(x=0, y=60)
I really just want to know if get_entry() can be put outside and be called inside of the convertFiles() function. I think that might not be possible because get_entry() needs variables that is inside the convertFiles(). I will be happy to hear your thoughts.
Yes, you can move get_entry() out of convertFiles(), but you need to pass those required variables to the function via arguments:
def get_entry(win, passp, pass_files, decrypted_data):
if passp:
for file in pass_files:
command1 = ["gpg", "-d", "--quiet", "--yes", "--pinentry-mode=loopback", f"--passphrase={passp}", f'{file}.gpg']
out = subprocess.check_output(command1, universal_newlines=False)
decrypted_data.append(out)
print('Asymmetric decryption is complete.')
win.destroy()
def convertFiles():
files = []
cname = my_lb.curselection()
for i in cname:
op = my_lb.get(i)
files.append(op)
if files == []:
messagebox.showinfo('', 'Please choose a file')
else:
pass_files = []
decrypted_data = []
if messagebox.askquestion('Convert', 'Are you sure to convert your file(s)?') == "yes":
kill_command = ["gpgconf", "--kill", "gpg-agent"]
kill_out = subprocess.check_output(kill_command, universal_newlines=False)
disable_button()
for val in files:
pass_files.append(f'{pwd}/.password-store/{val}')
newWindow = tk.Toplevel(root)
newWindow.title("Passphrase for Asymmetric Decryption")
newWindow.geometry("400x150")
newWindow.resizable(False,False)
tk.Label(newWindow,text ="Please put your passphrase for decryption.").place(x=0,y=0)
passp_entry = tk.Entry(newWindow)
passp_entry.place(x=0,y=30)
add_button = tk.Button(newWindow, text='Enter',
command=lambda: get_entry(newWindow, passp_entry.get(), pass_files, decrypted_data))
add_button.place(x=0, y=60)
Related
Link to the rep: https://github.com/elebumm/RedditVideoMakerBot
Error:
Traceback (most recent call last): File "main.py", line 6, in from reddit.subreddit import get_subreddit_threads File "/root/RedditVideoMakerBot-master/reddit/subreddit.py", line 81 for top_level_comment in submission.comments: ^
Script:
from os import getenv, environ
import praw
from utils.console import print_step, print_substep
from utils.subreddit import get_subreddit_undone
from utils.videos import check_done
from praw.models import MoreComments
TEXT_WHITELIST = set("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890")
def textify(text):
return "".join(filter(TEXT_WHITELIST.__contains__, text))
def get_subreddit_threads():
"""
Returns a list of threads from the AskReddit subreddit.
"""
global submission
print_substep("Logging into Reddit.")
content = {}
if str(getenv("REDDIT_2FA")).casefold() == "yes":
print("\nEnter your two-factor authentication code from your authenticator app.\n")
code = input("> ")
print()
pw = getenv("REDDIT_PASSWORD")
passkey = f"{pw}:{code}"
else:
passkey = getenv("REDDIT_PASSWORD")
reddit = praw.Reddit(
client_id=getenv("REDDIT_CLIENT_ID"),
client_secret=getenv("REDDIT_CLIENT_SECRET"),
user_agent="Accessing Reddit threads",
username=getenv("REDDIT_USERNAME"),
passkey=passkey,
check_for_async=False,
)
"""
Ask user for subreddit input
"""
print_step("Getting subreddit threads...")
if not getenv(
"SUBREDDIT"
): # note to self. you can have multiple subreddits via reddit.subreddit("redditdev+learnpython")
subreddit = reddit.subreddit(
input("What subreddit would you like to pull from? ")
) # if the env isnt set, ask user
else:
print_substep(f"Using subreddit: r/{getenv('SUBREDDIT')} from environment variable config")
subreddit = reddit.subreddit(
getenv("SUBREDDIT")
) # Allows you to specify in .env. Done for automation purposes.
if getenv("POST_ID"):
submission = reddit.submission(id=getenv("POST_ID"))
else:
threads = subreddit.hot(limit=25)
submission = get_subreddit_undone(threads, subreddit)
submission = check_done(submission) # double checking
if submission is None:
return get_subreddit_threads() # submission already done. rerun
upvotes = submission.score
ratio = submission.upvote_ratio * 100
num_comments = submission.num_comments
print_substep(f"Video will be: {submission.title} :thumbsup:", style="bold green")
print_substep(f"Thread has {upvotes} upvotes", style="bold blue")
print_substep(f"Thread has a upvote ratio of {ratio}%", style="bold blue")
print_substep(f"Thread has {num_comments} comments", style="bold blue")
environ["VIDEO_TITLE"] = str(textify(submission.title)) # todo use global instend of env vars
environ["VIDEO_ID"] = str(textify(submission.id))
content["thread_url"] = f"https://reddit.com{submission.permalink}"
content["thread_title"] = submission.title
# content["thread_content"] = submission.content
content["comments"7] = []
for top_level_comment in submission.comments:
if isinstance(top_level_comment, MoreComments):
continue
if top_level_comment.body in ["[removed]", "[deleted]"]:
continue # # see https://github.com/JasonLovesDoggo/RedditVideoMakerBot/issues/78
if not top_level_comment.stickied:
if len(top_level_comment.body) <= int(environ["MAX_COMMENT_LENGTH"]):
content["comments"].append(
{
"comment_body": top_level_comment.body,
"comment_url": top_level_comment.permalink,
"comment_id": top_level_comment.id,
}
)
print_substep("Received subreddit threads Successfully.", style="bold green")
return content
i have this weather app i made.
I have two problem with.
Fist is have try my code like this and it work well, for the fist part. But the problem is when they have more city with the same name. I can’t see the other one, because with this line of code i reach only the fist dictionaries.
'''
from tkinter import *
import requests
import json
root = Tk()
root.title("Weather app")
root.geometry("550x400")
root.configure(background="green")
var = IntVar()
def citylookup():
try:
api_request = requests.get(
"http://dataservice.accuweather.com/locations/v1/cities/autocomplete?apikey="
"xxxxxxxxxxxyyyyyyyyyyxxxxxxxxxxx" + city_search.get() + "&language=fr-FR")
api = json.loads(api_request.content)
localisation = api[0]["LocalizedName"]
region_adm = api[0]["AdministrativeArea"]["ID"]
id_key = api[0]["Key"]
# citylabel = Label(root, text=localisation + ", " + region_adm)
# citylabel.grid(row=1, column=0, columnspan=2)
button = Button(root, text=localisation + ", " + region_adm, command=forecast)
button.grid(row=1, column=0)
except Exception as e:
api = "Error..."
def forecast():
try:
api_request2 = requests.get("http://dataservice.accuweather.com/forecasts/v1/daily/1day/"
+ id_key.get() + "?apikey=xxxxxxxxxxxyyyyyyyyyyxxxxxxxxxxxg&language="
"fr-FR&details=true&metric=true")
api2 = json.loads(api_request2.content)
temperature = api2[0]["Temperature"]["Metric"]["Value"]
humidite = api2[0]["RelativeHumidity"]
uvindex = api2[0]["UVIndex"]
precipitation = api2[0]["PrecipitationSummary"]["Precipitation"]["Metric"]["Value"]
mylabel = Label(root,text="Aujourd'hui il fait \n" + temperature + text + "\nL'humidité relative est de " + humidite + "%\n" + "L'index UV est de " + uvindex + "\nPrécipitation prévue " + precipitation)
mylabel.grid(row=3, column=0, columnspan=2)
except Exception as e:
api = "Error..."
city_search = Entry(root)
city_search.grid(row=0, column=0, stick=W+E+N+S)
city_button = Button(root, text="Ville rechercher", command=citylookup)
city_button.grid(row=0, column=1, stick=W+E+N+S)
root.mainloop()
'''
So i have try a for loop in a json file. To retrieve all the city name in the dictionaries. (some city name have one, other 3, some 5 or more.)
for i in list(range(0, 10)) :
localisation = api[i][« LocalizedName »]
ect……
But with this i receive only one name and is the second in the dictionaries.
I have no idea’s of my mistake here…
SO for this fist problem i try, want wen i click on the button "citylookup" see all the city available in the dictionaries.
The second problem i have is for the command=forecast.
If i let my code like this i receive a message error( Unresolved reference "forecast")
Bit if i put my function "def forecast(): " whit no indent is ok no error for the forecast, but i receive the same message error with id_key.get()
And if i put my function over the function citylookup() : I receive a (no use of id_key) in the citylookup and a ( Unresolved reference "id_key") in the function "forecast"
and here i wan to do is wen i click in a city they show me the forecast.
I'm not sure if the indentation of this code in the question is the same as the code you have, but I will assume that it is.
I don't see why are you defining the forecast() function within the scope of except. I'd recommend first to get this function out of there.
for example:
def do_get_json(url):
try:
response = requests.get(url)
data = response.content()
json_data = json.loads(data)
return json_data
except Exception as ex:
raise RuntimeError("Cannot load") from ex
# get city lookup json object
def citylookup(city):
try:
# construct the city lookup url here and pass it to do_get_json
url = "...." + city
json_data = json_data = do_get_json(url)
return json_data
except RuntimeError as ex:
#handle exception for citylookup
# get forecast json object
def forecast(id_key):
try:
# construct the forecast url here and pass it to do_get_json
url = "..." + id_key
json_data = do_get_json(url)
return json_data
except RuntimeError as ex:
#handle exception for forecast
.
.
.
This way both functions are viaible to the whole file and not only to a single scope.
Your error is caused by something called Scope.
After this you can simply call them then parse, loop, save it however you like.
The trick here is that when you define static functions, you must use it after the definition.
An example of a non static function in python looks like this:
class SomeClass:
def __init__(self):
# body of constructor
def some_function(self, args):
# body of function
Notice the self argument. ^^
Here is an example of a better way to write your TK code:
root = Tk()
root.title("Weather app")
root.geometry("550x400")
root.configure(background="green")
var = IntVar()
# use a context dict to keep shared data
context = {}
city_search = Entry(root)
city_search.grid(row=0, column=0, stick=W+E+N+S)
def populate_city(context):
city_obj = citylookup(city_search.get())[0]
localisation = city_obj["LocalizedName"]
region_adm = city_obj["AdministrativeArea"]["ID"]
id_key = city_obj["Key"]
#save to context
context.id_key = id_key
citylabel = Label(root, text=localisation + ", " + region_adm)
citylabel.grid(row=1, column=0, columnspan=2)
city_button = Button(root, text="Ville rechercher", command= lambda: populate_city(context))
city_button.grid(row=0, column=1, stick=W+E+N+S)
# this probably need more work
def populate_forecast(context):
# get key from context
forcast_obj = forecast(context.id_key)
for elem in forecast_obj:
labels = []
temperature = elem["Temperature"]["Metric"]["Value"]
humidite = elem["RelativeHumidity"]
uvindex = elem["UVIndex"]
precipitation = elem["PrecipitationSummary"]["Precipitation"]["Metric"]["Value"]
mylabel = Label(root,text="Aujourd'hui il fait \n" + temperature + text + "\nL'humidité relative est de " + humidite + "%\n" + "L'index UV est de " + uvindex + "\nPrécipitation prévue " + precipitation)
mylabel.grid(row=3, column=0, columnspan=2)
lablels.append(mylable)
button = Button(root, text=localisation + ", " + region_adm, command= lambda: populate_forecast(context))
button.grid(row=1, column=0)
root.mainloop()
I have put the important word in bold so you could read some more about this, and not only Copy/Paste.
Topics to read about:
Context and State.
Functional Programing.
Refactoring.
Exception Handling.
Salut!.
I've solved the problem. The problem is related my %PATH%
I have a script which work with an argument. In powershell I've tried the command you can see below;
.\dsrf2csv.py C:\Python27\a\DSR_testdata.tsv.gz
And also you can see the script below,
def __init__(self, dsrf2csv_arg):
self.dsrf_filename = dsrf2csv_arg
dsrf_path, filename = os.path.split(self.dsrf_filename)
self.report_outfilename = os.path.join(dsrf_path, filename.replace('DSR', 'Report').replace('tsv', 'csv'))
self.summary_outfilename = os.path.join(dsrf_path, filename.replace('DSR', 'Summary').replace('tsv.gz', 'csv'))
But when I try to run this script there is no any action. How should I run this script with a file? (example : testdata.tsv.gz)
Note : Script and file in same location.
Full Scritp;
import argparse
import atexit
import collections
import csv
import gzip
import os
SKIP_ROWS = ['HEAD', '#HEAD', '#SY02', '#SY03', '#AS01', '#MW01', '#RU01',
'#SU03', '#LI01', '#FOOT']
REPORT_HEAD = ['Asset_ID', 'Asset_Title', 'Asset_Artist', 'Asset_ISRC',
'MW_Asset_ID', 'MW_Title', 'MW_ISWC', 'MW_Custom_ID',
'MW_Writers', 'Views', 'Owner_name', 'Ownership_Claim',
'Gross_Revenue', 'Amount_Payable', 'Video_IDs', 'Video_views']
SUMMARY_HEAD = ['SummaryRecordId', 'DistributionChannel',
'DistributionChannelDPID', 'CommercialModel', 'UseType',
'Territory', 'ServiceDescription', 'Usages', 'Users',
'Currency', 'NetRevenue', 'RightsController',
'RightsControllerPartyId', 'AllocatedUsages', 'AmountPayable',
'AllocatedNetRevenue']
class DsrfConverter(object):
"""Converts DSRF 3.0 to YouTube CSV."""
def __init__(self, dsrf2csv_arg):
""" Creating output file names """
self.dsrf_filename = dsrf2csv_arg
dsrf_path, filename = os.path.split(self.dsrf_filename)
print(dsrf_filename)
input("Press Enter to continue...")
self.report_outfilename = os.path.join(dsrf_path, filename.replace(
'DSR', 'Report').replace('tsv', 'csv'))
self.summary_outfilename = os.path.join(dsrf_path, filename.replace(
'DSR', 'Summary').replace('tsv.gz', 'csv'))
def parse_blocks(self, reader):
"""Generator for parsing all the blocks from the file.
Args:
reader: the handler of the input file
Yields:
block_lines: A full block as a list of rows.
"""
block_lines = []
current_block = None
for line in reader:
if line[0] in SKIP_ROWS:
continue
# Exit condition
if line[0] == 'FOOT':
yield block_lines
raise StopIteration()
line_block_number = int(line[1])
if current_block is None:
# Initialize
current_block = line_block_number
if line_block_number > current_block:
# End of block, yield and build a new one
yield block_lines
block_lines = []
current_block = line_block_number
block_lines.append(line)
# Also return last block
yield block_lines
def process_single_block(self, block):
"""Handles a single block in the DSR report.
Args:
block: Block as a list of lines.
Returns:
(summary_rows, report_row) tuple.
"""
views = 0
gross_revenue = 0
summary_rows = []
owners_data = {}
# Create an ordered dictionary with a key for every column.
report_row_dict = collections.OrderedDict(
[(column_name.lower(), '') for column_name in REPORT_HEAD])
for line in block:
if line[0] == 'SY02': # Save the financial Summary
summary_rows.append(line[1:])
continue
if line[0] == 'AS01': # Sound Recording information
report_row_dict['asset_id'] = line[3]
report_row_dict['asset_title'] = line[5]
report_row_dict['asset_artist'] = line[7]
report_row_dict['asset_isrc'] = line[4]
if line[0] == 'MW01': # Composition information
report_row_dict['mw_asset_id'] = line[2]
report_row_dict['mw_title'] = line[4]
report_row_dict['mw_iswc'] = line[3]
report_row_dict['mw_writers'] = line[6]
if line[0] == 'RU01': # Video level information
report_row_dict['video_ids'] = line[3]
report_row_dict['video_views'] = line[4]
if line[0] == 'SU03': # Usage data of Sound Recording Asset
# Summing up views and revenues for each sub-period
views += int(line[5])
gross_revenue += float(line[6])
report_row_dict['views'] = views
report_row_dict['gross_revenue'] = gross_revenue
if line[0] == 'LI01': # Ownership information
# if we already have parsed a LI01 line with that owner
if line[3] in owners_data:
# keep only the latest ownership
owners_data[line[3]]['ownership'] = line[6]
owners_data[line[3]]['amount_payable'] += float(line[9])
else:
# need to create the entry for that owner
data_dict = {'custom_id': line[5],
'ownership': line[6],
'amount_payable': float(line[9])}
owners_data[line[3]] = data_dict
# get rid of owners which do not have an ownership or an amount payable
owners_to_write = [o for o in owners_data
if (owners_data[o]['ownership'] > 0
and owners_data[o]['amount_payable'] > 0)]
report_row_dict['owner_name'] = '|'.join(owners_to_write)
report_row_dict['mw_custom_id'] = '|'.join([owners_data[o]
['custom_id']
for o in owners_to_write])
report_row_dict['ownership_claim'] = '|'.join([owners_data[o]
['ownership']
for o in owners_to_write])
report_row_dict['amount_payable'] = '|'.join([str(owners_data[o]
['amount_payable'])
for o in owners_to_write])
# Sanity check. The number of values must match the number of columns.
assert len(report_row_dict) == len(REPORT_HEAD), 'Row is wrong size :/'
return summary_rows, report_row_dict
def run(self):
finished = False
def removeFiles():
if not finished:
os.unlink(self.report_outfilename)
os.unlink(self.summary_outfilename)
atexit.register(removeFiles)
with gzip.open(self.dsrf_filename, 'rb') as dsr_file, gzip.open(
self.report_outfilename, 'wb') as report_file, open(
self.summary_outfilename, 'wb') as summary_file:
dsr_reader = csv.reader(dsr_file, delimiter='\t')
report_writer = csv.writer(report_file)
summary_writer = csv.writer(summary_file)
report_writer.writerow(REPORT_HEAD)
summary_writer.writerow(SUMMARY_HEAD)
for block in self.parse_blocks(dsr_reader):
summary_rows, report_row = self.process_single_block(block)
report_writer.writerow(report_row.values())
summary_writer.writerows(summary_rows)
finished = True
if __name__ == '__main__':
arg_parser = argparse.ArgumentParser(
description='Converts DDEX DSRF UGC profile reports to Standard CSV.')
required_args = arg_parser.add_argument_group('Required arguments')
required_args.add_argument('dsrf2csv_arg', type=str)
args = arg_parser.parse_args()
dsrf_converter = DsrfConverter(args.dsrf2csv_arg)
dsrf_converter.run()
In general to execute a python script in powershell like this .\script.py has two requirements:
Add the path to the python binaries to your %path%: $env:Path = $env:Path + ";C:\Path\to\python\binaries\"
Add the ending .py to the pathtext environment variable: $env:PATHEXT += ";.PY"
The latter will only be used in the current powershell session. If you want to add it to all future powershell sessions, add this line to your powershell profile (f.e. notepad $profile).
In your case there is also an issue with the python script you are trying to excute. def __init__(self) is an constructor for a class, like:
class Foo:
def __init__(self):
print "foo"
Did you give us your complete script?
I am using a simple python script to search and play songs on my laptop. The code goes as follows :-
import os
d_name = raw_input("enter drive name:-")
choice = raw_input("song or video(s/v):-")
if(choice == 's'):
s_name = raw_input("enter song name:- ")
flag = 1
elif(choice=='v'):
s_name = raw_input("enter video name:-")
flag = 2
if(flag == 1):
f_s_name = "start "+d_name+":/"+s_name+".mp3"
elif(flag == 2):
f_s_name = "start "+d_name+":/"+s_name+".mp4"
dir_list = os.listdir("d_name:/")
i=0
while(1):
if(not(os.system(f_s_name))):
break
else:
if(flag == 1):
f_s_name = "start "+d_name+":/"+dir_list[i]+"/"+s_name+".mp3"
elif(flag == 2):
f_s_name = "start "+d_name+":/"+dir_list[i]+"/"+s_name+".mp4"
i = i+1
the above program works fine but when one of the calls to the function os.system() fails until the required condition matches it pops out a dialog box claiming that the song is not there until it is found. How can i prevent popping up of that dialog box?
You'd use os.path.exists to test whether the file you're about to start actually exists; if it is not found, do not try to start that file:
import os
....
filename = '{}:/{}/{}.mp3'.format(d_name, dir_list[i], s_name)
if os.path.exists(filename):
system('start ' + filename)
else:
print "File {} was not found".format(filename)
I'm currently doing some work with multithreading and i'm trying to figure out why my program isn't working as intended.
def input_watcher():
while True:
input_file = os.path.abspath(raw_input('Input file name: '))
compiler = raw_input('Choose compiler: ')
if os.path.isfile(input_file):
obj = FileObject(input_file, compiler)
with file_lock:
files.append(obj)
print 'Adding %s with %s as compiler' % (obj.file_name, obj.compiler)
else:
print 'File does not exists'
This is running in one thread and it works fine until i start adding adding the second fileobject.
This is the output from the console:
Input file name: C:\Users\Victor\Dropbox\Private\multiFile\main.py
Choose compiler: aImport
Adding main.py with aImport as compiler
Input file name: main.py updated
C:\Users\Victor\Dropbox\Private\multiFile\main.py
Choose compiler: Input file name: Input file name: Input file name: Input file name:
The input filename keeps popping up the second i added the second filename and it ask for a compiler. The program keeps printing input file name until it crashes.'
I have other code running in a different thread, i don't think it has anything to do with the error, but tell me if you think you need to see it and i will post it.
the full code:
import multiprocessing
import threading
import os
import time
file_lock = threading.Lock()
update_interval = 0.1
class FileMethods(object):
def a_import(self):
self.mod_check()
class FileObject(FileMethods):
def __init__(self, full_name, compiler):
self.full_name = os.path.abspath(full_name)
self.file_name = os.path.basename(self.full_name)
self.path_name = os.path.dirname(self.full_name)
name, exstention = os.path.splitext(full_name)
self.concat_name = name + '-concat' + exstention
self.compiler = compiler
self.compiler_methods = {'aImport': self.a_import}
self.last_updated = os.path.getatime(self.full_name)
self.subfiles = []
self.last_subfiles_mod = {}
def exists(self):
return os.path.isfile(self.full_name)
def mod_check(self):
if self.last_updated < os.path.getmtime(self.full_name):
self.last_updated = os.path.getmtime(self.full_name)
print '%s updated' % self.file_name
return True
else:
return False
def sub_mod_check(self):
for s in self.subfiles:
if self.last_subfiles_mod.get(s) < os.path.getmtime(s):
self.last_subfiles_mod[s] = os.path.getmtime(s)
return True
return False
files = []
def input_watcher():
while True:
input_file = os.path.abspath(raw_input('Input file name: '))
compiler = raw_input('Choose compiler: ')
if os.path.isfile(input_file):
obj = FileObject(input_file, compiler)
with file_lock:
files.append(obj)
print 'Adding %s with %s as compiler' % (obj.file_name, obj.compiler)
else:
print 'File does not exists'
def file_manipulation():
if __name__ == '__main__':
for f in files:
p = multiprocessing.Process(target=f.compiler_methods.get(f.compiler)())
p.start()
#f.compiler_methods.get(f.compiler)()
def file_watcher():
while True:
with file_lock:
file_manipulation()
time.sleep(update_interval)
iw = threading.Thread(target=input_watcher)
fw = threading.Thread(target=file_watcher)
iw.start()
fw.start()
This is happening because you're not using an if __name__ == "__main__": guard, while also using multiprocessing.Process on Windows. Windows needs to re-import your module in the child processes it spawns, which means it will keep creating new threads to handle inputs and watch files. This, of course, is a recipe for disaster. Do this to fix the issue:
if __name__ == "__main__":
iw = threading.Thread(target=input_watcher)
fw = threading.Thread(target=file_watcher)
iw.start()
fw.start()
See the "Safe importing of the main module" section in the multiprocessing docs for more info.
I also have a feeling file_watcher isn't really doing what you want it to (it will keep re-spawning processes for files you've already processed), but that's not really related to the original question.