0

我正在尝试使用 subprocess.Popen(['cp', etc..]) 和 wait() 在 while 循环中传输和重命名一些文件。不幸的是,wait() 命令似乎没有正常工作,即没有等待文件完全复制到新目录。大多数情况下,文件复制得很好,但是,一小部分随机文件不会(每次运行脚本时文件都不相同),因此是零字节文件或不完整的文件。我也尝试过使用 subprocess.check_call() 但这也不起作用。当我打印 poll() 值时,它始终为零,这意味着该过程已经完成。请注意,我正在处理的所有文件都在 150KB 范围内。我的 python 脚本正在 pyraf 中运行,使用 python 2.7,iraf 的 python 版本(图像缩减和分析工具),因为我使用的是 iraf 例程。

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.01 秒的 shell 睡眠时间,以强制其他两个进程在返回一个已完成的进程之前完成,那可能会解决它。也许是这样的,虽然我不确定确切的语法:

 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()       

希望这能让您了解我正在尝试做的事情。我一直在尝试很多不同的事情,并一直在寻找解决这个问题的方法,但我真的被困住了。

干杯,布雷特

4

3 回答 3

0

这不是一个完整的解决方案,也不是一个令人满意的解决方案,但它是我想出的最好的解决方案,并且工作时间约为 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 在到达 sleep 命令之前不会收到完成的信号。我相信这部分工作得很好。唯一的问题是,当我到达此命令时,用于创建 eps 文件的 iraf 例程很少能以足够快的速度创建它们。

        #endif

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

这是一个非常笨拙的解决方案,一点也不满足,但它确实在 99.9% 的时间内有效。如果有人有更好的解决方案,请告诉我。这是一个非常令人沮丧的问题,我问过的每个人都无法提出更好的建议(包括在我的天文部门经常使用 python 编程的人)。

于 2013-02-05T01:18:36.110 回答
0

您是否考虑过使用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 %s %s%s
rm %s
sleep %s
''' % (eps_file_list[0], ccf_output_dir, object_name_sub, eps_file_list[0], 0.01)
于 2013-01-22T07:55:58.517 回答
0

也许以下就足够了:

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()
于 2013-01-22T07:51:13.727 回答