簡體   English   中英

如何強制wait()完全等待subprocess.Popen()完成

[英]How to force wait() to completely wait for subprocess.Popen() to complete

我正在嘗試使用subprocess.Popen(['cp',etc ..])和wait()在while循環中傳輸和重命名一些文件。 不幸的是,似乎wait()命令無法正常工作,即不等待文件完全復制到新目錄。 大多數情況下,文件復制良好,但是,一小部分隨機文件卻不會(每次運行腳本時都不是同一文件),因此是零字節文件或不完整文件。 我也嘗試過使用subprocess.check_call(),但這也不起作用。 當我打印poll()值時,它始終為零,這意味着過程已完成。 請注意,我正在處理的所有文件都在150KB范圍內。 由於我使用的是iraf例程,因此我的python腳本正在使用python 2.7(iraf(圖像縮小和分析工具)的python版本)在pyraf中運行。 有什么方法可以強制Popen()或check_call()等待文件傳輸完成?

while count <= ncross_correlate and skip_flag != 's':
   ...more stuff
   try:
      iraf.rv.fxcor (object_fits, template_fits, apertures="*", cursor="",
      continuum="both", filter="both", rebin="smallest", pixcorr="no", 
      osample=osample_reg, rsample=osample_reg, apodize=0.1, function="gaussian",
      width="INDEF", height=0., peak="no", minwidth=3., maxwidth=21., weights=1.,
      background=0., window=300., wincenter="INDEF", output=output_name, verbose="long",
      imupdate="no", graphics="stdgraph", interactive="no", autowrite="yes",
      autodraw="yes", ccftype="image", observatory="aao", continpars="", filtpars="", 
      keywpars="")

      # Create a eps file of the cross_correlation file.
      gki_output_name = output_name + '.gki'
      iraf.plot.sgikern (gki_output_name, device='eps', generic='no', debug='no',
      verbose='no', gkiunit='no')

不幸的是,將以fxcor創建的.gki文件轉換為iraf之外的某些可讀格式的唯一方法是調用iraf任務sgikern,該任務將.eps文件轉儲到我的iraf / iraf /目錄中,而沒有提供更改文件名或目錄位置。 實際上,文件名是隨機生成的。 非常令人沮喪!!! 另請注意,使用iraf.plot.sgikern創建的任何eps文件都沒有問題(即,開頭沒有0 KB文件)。 復制和重命名是我遇到的問題。

      # Find the eps file in /iraf/iraf/, rename it, and move to proper output location.
      iraf_dir = '/iraf/iraf/'
      eps_file_list = glob.glob(iraf_dir + 'sgi' + '*.eps')

      ...more code

在這一點上,我已經嘗試使用check_call()或Popen():

      subprocess.check_call(['cp', eps_file_list[0], ccf_output_dir + object_name_sub +
                            '.eps'], stdout=subprocess.PIPE)
      subprocess.check_call(['rm', eps_file_list[0]], stdout=subprocess.PIPE)

要么

      process1 = subprocess.Popen(['cp', eps_file_list[0], ccf_output_dir +
                                  object_name_sub + '.eps'], stdout=subprocess.PIPE)
      process1.wait()
      process2 = subprocess.Popen(['rm', eps_file_list[0]], stdout=subprocess.PIPE)
      process2.wait()

      ...more stuff

   # end of try statement
#end of while statement  

我估計是否可以將兩個Popen語句組合為一個Popen語句,並且還包括大約0.01s的shell睡眠時間,以強制其他兩個進程在返回已完成的進程之前完成,這可能會解決該問題。 也許像這樣,盡管我不確定確切的sendax:

 process1 = subprocess.Popen(['cp', eps_file_list[0], ccf_output_dir +
            object_name_sub + '.eps']; ['rm', eps_file_list[0]]; ['sleep', 0.01],
            stdout=subprocess.PIPE)
 process1.wait()       

希望這能使您對我正在嘗試做的事情有所了解。 我一直在嘗試許多不同的事情,並四處尋找解決這個問題的方法,但我確實陷入了困境。

干杯,布雷特

也許以下內容就足夠了:

subprocess.check_call(['mv', eps_file_list[0], ccf_output_dir + object_name_sub +
                        '.eps'], stdout=subprocess.PIPE)

process1 = subprocess.Popen(['mv', eps_file_list[0], ccf_output_dir +
                              object_name_sub + '.eps'], stdout=subprocess.PIPE)
process1.wait()

你有沒有考慮使用shutil.copyfile用於復制和os.remove的缺失?

如果您真的想使用Subprocess,我相信語法是這樣的:

process1 = subprocess.Popen('cp ' + eps_file_list[0] + ' ' + ccf_output_dir +
        object_name_sub + '.eps; rm ' + eps_file_list[0] ' + '; sleep 0.01',
        stdout=subprocess.PIPE)

這樣,您正在調用的命令全部都在一個字符串中: 'cp whatever foo/bar.eps; rm whatever; sleep 0.01' 'cp whatever foo/bar.eps; rm whatever; sleep 0.01'

您還可以使用三引號將字符串格式化,並將命令放在單獨的行上:

'''
cp %s %s%s
rm %s
sleep %s
''' % (eps_file_list[0], ccf_output_dir, object_name_sub, eps_file_list[0], 0.01)

這不是一個完整的解決方案,也不是一個令人滿意的解決方案,但這是我所能提供的最好的解決方案,並且可以在大約99.9%的時間內工作(我創建的4000+ eps中有5個文件要么是0字節,要么是不完整的)。 這是對我最初執行此操作的方式的一種改進,該方式大約有95%的時間成功。 我粘貼了以下代碼:

     try:
        iraf.rv.fxcor (object_fits, template_fits, apertures="*", cursor="",
        continuum="both", filter="both", rebin="smallest", pixcorr="no", osample=osample_reg,
        rsample=osample_reg, apodize=0.1, function="gaussian", width="INDEF", height=0., peak="no",
        minwidth=3., maxwidth=21., weights=1., background=0., window=300.,
        wincenter="INDEF", output=output_name, verbose="long", imupdate="no",
        graphics="stdgraph", interactive="no", autowrite="yes", autodraw="yes",
        ccftype="image", observatory="aao", continpars="", filtpars="", keywpars="")

        # Create a eps file of the cross_correlation file.
        gki_output_name = output_name + '.gki'
        iraf.plot.sgikern (gki_output_name, device='eps', generic='no', debug='no',
        verbose='no', gkiunit='no')
        time.sleep(0.25)

當我發現在我的iraf目錄中創建的某些ps文件在我的代碼嘗試將文件移至另一個目錄時尚未完全寫入時,我在此處放置了一個卧鋪。

        # Find the eps file in /iraf/iraf/, rename it, move to proper output location, and delete the old eps file.
        iraf_dir = '/iraf/iraf/'
        eps_file_list = glob.glob(iraf_dir + 'sgi' + '*.eps')

        ...continuation of code

        if len(eps_file_list) == 1:
           eps_file_sub = os.path.basename(eps_file_list[0])

           cmd1 = 'cp {0} {1}'.format(eps_file_list[0], ccf_output_dir + object_name_sub + '.eps')
           cmd2 = 'rm {0}'.format(eps_file_list[0])
           cmd3 = 'sleep 0.05'
           process1 = subprocess.Popen("{}; {}; {}".format(cmd1, cmd2, cmd3), shell=True, stdout=subprocess.PIPE)
           process1.wait()

通過process1,我將發送三個子進程shell命令。 第一種是將eps文件從我的/ iraf目錄復制到另一個目錄(首先創建它們的iraf函數不允許我為這些文件提供適當的名稱或輸出位置)。 第二個是從我的/ iraf目錄中刪除eps文件。 第三個命令用於強制內核進入睡眠狀態。 這樣,直到到達睡眠命令,Python才會收到完整的信號。 我相信這部分效果很好。 唯一的問題是,當我到達此命令時,很少有用於創建eps文件的iraf例程無法足夠快地創建它們。

        #endif

        num_cross = num_cross + 1
     #Endtry
     ...more code

這是一個非常笨拙的解決方案,雖然不能滿足最低要求,但它確實有99.9%的時間可以工作。 如果有人有更好的解決方案,請告訴我。 這是一個非常令人沮喪的問題,我問過的每個人都無法提出更好的建議(包括在我的astro部門定期使用python編程的人)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM