2011-04-23 78 views
2

所以我理解遞歸限制爲1000的原因。我想連續運行一個腳本,但是我正確理解最終會達到遞歸限制(即使我將它設置得更高),並且Python會打破?因爲我可以讓操作系統繼續重新啓動腳本,但是我認爲在腳本本身中可能會採用更優雅的解決方案(交換線程??)。Python遞歸限制

我的腳本:

import os 
import subprocess 
import time 
import logging 
import datetime 
from sys import argv 

if len(argv) < 3: 
    exit('Please provide two arguments - Source Destination') 


LOC_DIR = argv[1] 
REM_DIR = argv[2] 

POLL_INT = 10 
RUN_INT = 60 
FILE_EXT = '.mov' 


# logging setup 
logging.basicConfig(filename='%s' % os.path.join(LOC_DIR, '%s the_log.log' % datetime.datetime.now()),level=logging.DEBUG) 

# make an easy print and logging function 
def printLog(string): 
    print '%s %s' % (datetime.datetime.now(), string) 
    logging.info('%s %s' % (datetime.datetime.now(), string)) 


# get the files with absolute paths 
def getFiles(path): 
    return [os.path.join(path, entry) for entry in os.listdir(path)] 


# check if file is still being copied (file size has changed within the poll interval) 
def checkSize(path): 
    same = False 
    while same is False: 
     printLog("Processing '%s'" % os.path.basename(path)) 
     printLog('Waiting %s seconds for any filesize change' % POLL_INT) 
     size1 = os.path.getsize(path) 
     time.sleep(POLL_INT) 
     size2 = os.path.getsize(path) 
     if size1 == size2: 
      same = True 
      printLog('File size stayed the same for %s seconds' % POLL_INT) 
      return same 
     else: 
      printLog('File size change detected. Waiting a further %s seconds' % POLL_INT) 


# check if correct file extension 
def checkExt(path): 
    if path.endswith(FILE_EXT): 
     return True 


# rsync subprocess 
def rsyncFile(path): 
    printLog("Syncing file '%s'" % os.path.basename(path)) 
    try: 
     command = ['rsync', '-a', '--remove-source-files', path, REM_DIR] 
     p = subprocess.Popen(command, stdout=subprocess.PIPE) 
     for line in p.stdout: 
      printLog("rsync: '%s'" %line) 
     p.wait() 
     if p.returncode == 0: 
      printLog('<<< File synced successfully :) >>>') 
     elif p.returncode == 10: 
      printLog('****** Please check your internet connection!! ****** Rsync error code: %s' % p.returncode) 
     else: 
      printLog('There was a problem. Error code: %s' % p.returncode) 
    except Exception as e: 
     logging.debug(e) 


# main logic 
def main(): 
    all_files = getFiles(LOC_DIR) 
    files = [] 
    for f in all_files: 
     if checkExt(f): 
      files.append(f) 
    if len(files) == 1: 
     printLog('<<< Found %s matching file >>>' % len(files)) 
    elif len(files) > 1: 
     printLog('<<< Found %s matching files >>>' % len(files)) 
    for f in files: 
     if checkSize(f): 
      rsyncFile(f) 
    printLog('No files found. Checking again in %s seconds' % RUN_INT) 
    time.sleep(RUN_INT) 
    printLog('Checking for files') 
    main() 

if __name__ == "__main__": 


    main() 
+2

計算機科學告訴我們,任何遞歸都可以重寫爲一個循環。 – 9000 2011-04-23 05:27:51

+8

計算機科學也告訴我們,任何軟件都可以用圖靈機寫出來,但我敢打賭你不想這樣做。 – mmj 2012-04-18 00:00:13

回答

6

CPython中有遞歸沒有優化,所以你真的想避免有利於深遞歸碼規律的循環:

def main(): 
    while True: 
     all_files = getFiles(LOC_DIR) 
     files = [] 
     for f in all_files: 
      if checkExt(f): 
       files.append(f) 
     if len(files) == 1: 
      printLog('<<< Found %s matching file >>>' % len(files)) 
     elif len(files) > 1: 
      printLog('<<< Found %s matching files >>>' % len(files)) 
     for f in files: 
      if checkSize(f): 
       rsyncFile(f) 
     printLog('No files found. Checking again in %s seconds' % RUN_INT) 
     time.sleep(RUN_INT) 
     printLog('Checking for files') 

if __name__ == "__main__":  
    main() 
+0

謝謝Blender,我不知道我在不必要地遞歸。多謝! – MFB 2011-04-23 05:40:23

+0

不客氣! – Blender 2011-04-23 05:42:04

1

你以錯誤的方式去了解這一點。

用循環替換主循環。

# main logic 
def main(): 
    while True: 
     all_files = getFiles(LOC_DIR) 
     files = [] 
     for f in all_files: 
      if checkExt(f): 
       files.append(f) 
     if len(files) == 1: 
      printLog('<<< Found %s matching file >>>' % len(files)) 
     elif len(files) > 1: 
      printLog('<<< Found %s matching files >>>' % len(files)) 
     for f in files: 
      if checkSize(f): 
       rsyncFile(f) 
     printLog('No files found. Checking again in %s seconds' % RUN_INT) 
     time.sleep(RUN_INT) 
     printLog('Checking for files') 
+0

感謝Nick,我也會試試這個。乾杯! – MFB 2011-04-23 05:41:14

0

的遞歸限制設置爲僅從我的理解遞歸函數,所以如果你真的想重複運行一些東西,你可以簡單地運行。

while True: 
    #repeated stuff goes here 

遞歸是一個了不起的工具,但小心處理,往往可以結束了燒你。你說得對,因爲python只能遞歸地調用1000次調用,所以如果遞歸方法沒有完成,那麼異常就會被拋出。

Goodluck。

+0

謝謝Dusty,我甚至不知道我使用遞歸..完全無意!乾杯 – MFB 2011-04-23 05:36:34