Вместо того, чтобы пытаться заставить multiprocessing.Process()
работать на вас, возможно, вам следует использовать другой инструмент, такой как apply_async()
с многопроцессорной обработкой.Pool ():
def main(argv):
# parse command line args
...
# set up variables
...
# set up multiprocessing Pool
pool = multiprocessing.Pool()
try:
watch_dir(watch_dir, download_dir, pool)
# catch whatever kind of exception you expect to end your infinite loop
# you can omit this try/except if you really think your script will
# run "forever" and you're okay with zombies should it crash
except KeyboardInterrupt:
pool.close()
pool.join()
def watch_dir(wDir, dDir, pool):
# Grab the current watch directory listing
before = dict([(f, None) for f in os.listdir (wDir)])
# Loop FOREVER
while 1:
# sleep for 10 secs
time.sleep(10)
# Grab the current dir listing
after = dict([(f, None) for f in os.listdir (wDir)])
# Get the list of new files
added = [f for f in after if not f in before]
# Get the list of deleted files
removed = [f for f in before if not f in after]
if added:
# We have new files, do your stuff
print "Added: ", ", ".join(added)
# launch the function in a subprocess - this is NON-BLOCKING
pool.apply_async(child, (added, wDir, dDir))
if removed:
# tell the user the file was deleted
print "Removed: ", ", ".join(removed)
# Set before to the current
before = after
def child(filename, wDir, dDir):
# Open filename and extract the url
...
# Download the file and to the dDir directory
...
# Delete filename from the watch directory
...
# simply return to "exit cleanly"
return
multiprocessing.Pool()
- это пул рабочих подпроцессов, в которые вы можете отправлять «задания». Вызов функции pool.apply_async()
приводит к тому, что один из подпроцессов запускает вашу функцию с предоставленными аргументами асинхронно и не требует объединения, пока ваш скрипт не выполнит всю свою работу и не закроет весь пул. Библиотека управляет деталями для вас.
Я думаю, что это послужит вам лучше, чем текущий принятый ответ по следующим причинам:
1. Это устраняет ненужную сложность запуска дополнительных потоков и очередей только для управления подпроцессами.
2. Он использует библиотечные подпрограммы, которые созданы специально для этой цели , так что вы получите выгоду от будущих улучшений библиотеки.
3. ИМХО, это гораздо удобнее в обслуживании.
4. Это более гибкий. Если вы однажды решите, что хотите увидеть возвращаемое значение из своих подпроцессов, вы можете сохранить возвращаемое значение из вызова apply_async()
(объект результата ) и проверить его в любое время. Вы можете хранить их в списке и обрабатывать как пакеты, когда ваш список становится больше определенного размера. Вы можете переместить создание пула в функцию watch_dir()
и покончить с попыткой /, за исключением случаев, когда вас действительно не волнует, что произойдет, если «бесконечный» цикл прерывается. Если вы поместили какое-то условие разрыва в (в настоящее время) бесконечный цикл, вы можете просто добавить pool.close()
и pool.join()
после цикла, и все будет очищено.