问题 在R中使用system()调用python来运行模拟python控制台的python脚本


我希望将一大块Python代码传递给R中的Python system('python ...'),我想知道在这种情况下是否有一种简单的方法来模拟python控制台。例如,假设代码是 "print 'hello world'",我怎样才能在R中获得这样的输出?

>>> print 'hello world'
hello world

这只显示输出:

> system("python -c 'print \"hello world\"'")
hello world

谢谢!

顺便说一下,我问道 R-帮助 但还没有得到回复(如果我这样做,我会在这里发布答案)。


12505
2018-04-14 17:25


起源

你考虑过使用RPy吗? - Ignacio Vazquez-Abrams
问题是我想在R中运行python代码,而不是在python中运行R代码,所以RPy可能不是这里的选项;还是我错过了一些明显的东西?...... - Yihui Xie


答案:


你的意思是这样的吗?

export NUM=10
R -q -e "rnorm($NUM)"

您可能还想看看 littler  - http://dirk.eddelbuettel.com/code/littler.html

更新

根据您的评论,我认为我开始更好地理解您的问题。你问的是在R shell中运行python。

所以这是一个例子: -

# code in a file named myfirstpythonfile.py

a = 1 
b = 19
c = 3 
mylist = [a, b, c]
for item in mylist:
    print item

因此,在你的R shell中,执行以下操作:

> system('python myfirstpythonfile.py')
1
19
3

基本上,你可以简单地打电话 python /path/to/your/python/file.py 执行一段python代码。

在我的情况下,我可以简单地打电话 python myfirstpythonfile.py 假设我在我的python文件所在的同一目录(路径)中启动了我的R shell。

进一步更新

如果你  想要打印出源代码,这是一种可能的强力方法。在你的R shell: -

> system('python -c "import sys; sys.stdout.write(file(\'myfirstpythonfile.py\', \'r\').read());"; python myfirstpythonfile.py')
a = 1
b = 19
c = 3
mylist = [a, b, c]
for item in mylist:
    print item
1
19
3

并进一步更新:-)

因此,如果目的是在执行代码之前打印python代码,我们可以使用python跟踪模块(参考: http://docs.python.org/library/trace.html)。在命令行中,我们使用 -m 调用python模块的选项,我们为它后面的python模块指定选项。

所以对于我上面的例子,它将是: -

$ python -m trace --trace myfirstpythonfile.py
 --- modulename: myfirstpythonfile, funcname: <module>
myfirstpythonfile.py(1): a = 1
myfirstpythonfile.py(2): b = 19
myfirstpythonfile.py(3): c = 3
myfirstpythonfile.py(4): mylist = [a, b, c]
myfirstpythonfile.py(5): for item in mylist:
myfirstpythonfile.py(6):     print item
1
myfirstpythonfile.py(5): for item in mylist:
myfirstpythonfile.py(6):     print item
19
myfirstpythonfile.py(5): for item in mylist:
myfirstpythonfile.py(6):     print item
3
myfirstpythonfile.py(5): for item in mylist:
 --- modulename: trace, funcname: _unsettrace
trace.py(80):         sys.settrace(None)

我们可以看到,跟踪python代码的确切行,紧接着执行结果并将其输出到stdout。


11
2018-04-14 17:30



不,我主要是想要一种像我们调用方式那样运行python脚本的方法 source(file, echo=TRUE) 在R.它看起来像 code python中的模块可能有帮助(read-eval-print循环),但我想知道python是否具有可以直接调用的函数。我是python的新手。谢谢! - Yihui Xie
您只需通过调用“python thefilename”在命令行中运行python脚本(python文件中的python代码块)。所以你的 system()在R shell中调用也应该这样做。我已经更新了上面的答案。 - Calvin Cheng
是的,但问题是,如何在执行前打印python代码。是否有一些python标志,如 -x 对于bash脚本? - smu
我不认为有相当的 -x 在bash for python中。 - Calvin Cheng
但如果方案是做调试(根据我的理解, -x 然后,在bash中主要用于调试目的) python -d 有点类似,但它仍然没有打印出源代码。 - Calvin Cheng


system命令有一个名为的选项 intern = FALSE。做这个 TRUE 无论之前看到什么输出,都将存储在变量中。

现在使用此选项运行系统命令,您应该直接在变量中获取输出。喜欢这个

tmp <- system("python -c 'print \"hello world\"'",intern=T)

2
2017-08-08 14:14



对不起,但这不是我想要的。我想模仿python控制台(REPL接口);不仅要执行整个代码,还要在此之后收集结果。我知道 system(..., intern=TRUE)。 - Yihui Xie


我解决这个问题的方法是定义我自己的函数,粘贴参数,写出临时的.py文件,然后通过系统调用执行python文件。以下是调用ArcGIS的欧几里德距离函数的示例:

py.EucDistance = function(poly_path,poly_name,snap_raster,out_raster_path_name,maximum_distance,mask){

    py_path = 'G:/Faculty/Mann/EucDistance_temp.py'
    poly_path_name = paste(poly_path,poly_name, sep='')

    fileConn<-file(paste(py_path))
    writeLines(c(
        paste('import arcpy'),
        paste('from arcpy import env'),
        paste('from arcpy.sa import *'),
        paste('arcpy.CheckOutExtension("spatial")'),

        paste('out_raster_path_name = "',out_raster_path_name,'"',sep=""),
        paste('snap_raster = "',snap_raster,'"',sep=""),
        paste('cellsize =arcpy.GetRasterProperties_management(snap_raster,"CELLSIZEX")'),
        paste('mask = "',mask,'"',sep=""),
        paste('maximum_distance = "',maximum_distance,'"',sep=""),
        paste('sr = arcpy.Describe(snap_raster).spatialReference'),

        paste('arcpy.env.overwriteOutput = True'),
        paste('arcpy.env.snapRaster = "',snap_raster,'"',sep=""),
        paste('arcpy.env.mask = mask'),
        paste('arcpy.env.scratchWorkspace ="G:/Faculty/Mann/Historic_BCM/Aggregated1080/Scratch.gdb"'),
        paste('arcpy.env.outputCoordinateSystem = sr'),


        # get spatial reference for raster and force output to that
        paste('sr = arcpy.Describe(snap_raster).spatialReference'),
        paste('py_projection = sr.exportToString()'),     
        paste('arcpy.env.extent = snap_raster'),
        paste('poly_name = "',poly_name,'"',sep=""),
        paste('poly_path_name = "',poly_path_name,'"',sep=""),

        paste('holder = EucDistance(poly_path_name, maximum_distance, cellsize, "")'),
        paste('holder = SetNull(holder < -9999, holder)'),
        paste('holder.save(out_raster_path_name) ')

    ), fileConn, sep = "\n")
    close(fileConn)

    system(paste('C:\\Python27\\ArcGIS10.1\\python.exe', py_path))
}

0
2018-05-02 13:23