【问题标题】:Can't seem to get fortran executable to run correctly through python似乎无法让 fortran 可执行文件通过 python 正确运行
【发布时间】:2012-05-26 06:40:09
【问题描述】:

我在 SO 和其他网站上阅读了许多不同的主题,但无法直接回答我的问题。目前我有这个运行完全正常的python脚本,除了没有调用运行fortran程序正常工作。我尝试过使用子进程命令、os.system 命令、打开通过 python 打开的 bash 脚本文件,但没有运气。这是我遇到的一些示例和错误。

一次尝试:

subprocess.Popen(["sh", "{0}{1}".format(SCRIPTS,"qlmtconvertf.sh"), "qlmt"], shell=False, stdout=subprocess.PIPE)

这会给出程序无法正确读取文件的错误。

    forrtl: severe (24): end-of-file during read, unit 1, file /home/akoufos/lapw/Ar/lda/bcc55_mt1.5_lo_e8_o4/DOS/lat70/qlmt

另一个尝试:

subprocess.Popen(["./{0}{1}".format(SOURCE,"qlmtconvertf"), "qlmt"], shell=False, stdout=subprocess.PIPE)

这会导致找不到文件的错误。

    File "/home/akoufos/lapw/Scripts_Plots/LAPWanalysis.py", line 59, in DOS
subprocess.Popen(["./{0}{1}".format(SOURCE,"qlmtconvertf"), "qlmt"], shell=False, stdout=subprocess.PIPE)
    File "/usr/lib64/python2.7/subprocess.py", line 672, in __init__
errread, errwrite)
    File "/usr/lib64/python2.7/subprocess.py", line 1202, in _execute_child
raise child_exception
    OSError: [Errno 2] No such file or directory

又一次尝试:

os.system("{0}{1}".format(SOURCE,"qlmtconvertf qlmt"))

这给出了与第一个示例等效的错误。在所有示例 SOURCE="/home/myusername/lapw/Source/",fortran 源文件所在的位置,SCRIPTS="/home/myusername/lapw/Scripts_Plots/",其中我有其他文件和 python 脚本,qlmtconvertf是一个已编译的 fortran 程序,而 qlmt 是 qlmtconvertf 读取的文件。如果我在 shell 中调用它,这个源代码完全可以正常工作,就像我做过无数次一样,但我正在尝试自动调用这些代码。我也编写了一个 bash 脚本,它可以满足我的需要,但我正在尝试通过 python 来做所有事情。对于我做错了什么以及正在发生的事情的任何想法、建议或答案将不胜感激。提前谢谢大家。

编辑:我得到了它与弗朗西斯下面给出的建议一起工作。我必须保留完整的路径(即 /home/username/etc)和 os.path.join 才能正确调用程序。

    import os.path
    LAPW = "/home/myusername/lapw/"
    SOURCE = os.path.join(LAPW,'Source')
    SCRIPTS = os.path.join(LAPW,'Scripts_Plots')
    QLMTCONVERT = os.path.join(SOURCE,'qlmtconvertf')
    qargs = [QLMTCONVERT,'qlmt']
    #CALLING PROGRAM
    subprocess.Popen(qargs, stdout=subprocess.PIPE).communicate(input=None)

为了让它正常工作,我还必须关闭我在 python 脚本中创建的“qlmt”文件。我也在包含“qlmt”文件的目录中工作。

(edit 还在子进程的末尾添加了.communicate(input=None)。这对于此进程调用来说是不必要的,但对于我在脚本中尝试使用进程正在创建的文件。据我了解,.communicate 与进程对话,基本上在执行下一条 python 行之前等待它完成。类似于.wait(),但更高级。如果更了解这一点的人想要详细说明,请随意。编辑

我不确定为什么这种方法有效,但是使用字符串作为子进程的输入会产生错误。如果有人对此有任何见解,如果您能传授您的知识,我将不胜感激。谢谢大家的帮助。

【问题讨论】:

  • 你试过shell=True吗?我通常在调用外部程序时发现这是必要的。
  • 你写这些帖子的方式很有趣,看了 20 遍,仍然忘记提及。我在第二个例子中尝试了shell=True,有和没有./。两者似乎都不起作用。我也尝试使用~/lapw 作为文件夹名称而不是完整路径。同样,这两种方法都不会给出更多有用的错误。在第一个示例中尝试它会打开 shell 提示符,但似乎也不起作用,但不会运行程序。我将对此进行更多研究,因为似乎没有调用 qlmtconvert。感谢您的建议。
  • 在尝试运行可执行文件之前,您是否尝试将当前工作目录更改为可执行文件所在的目录?我使用了几个希望从它们的目录运行的 fortran 程序。
  • @arifwn:不,我没有,但这应该不是问题,正如我在上面建议的那样,如果我单独在 shell 中调用它,程序运行良好。即我在包含“qlmt”的目录中工作时从 shell 调用/home/myusername/lapw/Source/qlmtconvertf qlmt。感谢您的建议。
  • @falconskull:是的,有时要记住的东西太多了。很高兴您似乎找到了解决方案。 FWIW,我尝试使用 subprocess 调用(.call().Popen())从 Python 程序运行一个非常简单的 FORTRAN 程序,发现我需要 shell=True 才能使其工作。但是,您似乎在 Windows 上(我现在无法访问)而我在 Linux 上,所以 YMMV。

标签: python fortran subprocess os.system


【解决方案1】:

我想你忘记了文件名中的斜线:

"{0}{1}".format(SOURCE,"qlmtconvertf qlmt") == '/home/myusername/lapw/Sourceqlmtconvertf qlmt'

我猜你是这个意思?

"{0}/{1}".format(SOURCE,"qlmtconvertf qlmt") == '/home/myusername/lapw/Source/qlmtconvertf qlmt'

我建议使用os.path.join 而不是直接构造字符串来创建路径名:

import os.path

executable = os.path.join(SOURCE, 'qlmtconvertf')
args = ['qlmt']

subprocess.Popen(executable+args, stdout=subprocess.PIPE)

【讨论】:

  • 我实际上有/ 我只是忘了将它添加到我放弃的变量中。对困惑感到抱歉。但是,我没有意识到os.path.join 选项。我将开始使用它,现在将尝试一下。谢谢。
  • 更新:这个选项似乎有帮助。但是,我不太明白为什么会这样,但是将路径作为与os.path.join 完全相同的输出的字符串是行不通的。你对此有什么见解吗?非常感谢您的帮助!
  • 双重检查(使用断言语句)字符串实际上是相同的。 os.path.join 智能地以依赖于操作系统的方式连接路径段,但它仍然返回一个字符串。
  • 我不会费心去测试它,因为它正在使用你的方法。对于这些事情,我还不如使用比字符串方式更正确的方法!我一直在调整我的所有脚本以使用这种方式,并且事情运行得更好,并使我的脚本更易于阅读。所以我非常感谢你的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多