命令行腳本
通過Windows 或Linux終端環境命令行運行R和Python腳本類似。要運行的命令被分解成以下部分:
<command_to_run> <path_to_script> <any_additional_arguments>
參數說明
▲<command> 是可執行的命令 (R代碼中是 Rscript, Python代碼中是Python)
▲<path_to_script>是執行腳本所在的完整或相對文件路徑。需要注意的是,如果在路徑名中有空格,整個文件路徑必須用雙引號括起來。
▲<any_additional_arguments>這是空格分隔的參數列表用來解析腳本本身。請注意,這些不能作為字符串傳遞。
例如,打開一個終端環境並運行R腳本,命令如下:Rscript path/to/myscript.R arg1 arg2 arg3
請注意以下問題:
對於Rscript 和Python 命令必須在你所在的路徑中執行,否則你需要提供文件的完整路徑。含有空格符的路徑名會產生問題,尤其是在Window系統中,因此必須用雙引號括起來,這樣才被認為是一個單獨的文件路徑。
R語言中訪問命令行參數
上面的例子中,arg1,arg2 和 arg3是用來解析可執行R腳本的參數,可以使用commandArgs函數訪問
##myscript.py
#獲取命令行參數
myArgs <- commandArgs(trailingOnly = TRUE)
#myArgs是所有參數的特征向量
print(myArgs) print(class(myArgs))
通過設置trailingOnly 為TRUE,myArgs向量中只包含添加到命令行的參數。如果默認設置為FALSE ,myArgs向量中還包含其它參數,比如剛被執行的腳本路徑。
Python語言中訪問命令行參數
通過下面的命令行執行Python腳本:
python path/to/myscript.py arg1 arg2 arg3
通過在Python腳本中導入sys模塊訪問arg1, arg2 和arg3參數。 sys模塊包含了系統具體的參數和函數,在這里,我們只對 argv的屬性感興趣。這個argv屬性是所有被傳遞到當前正在執行腳本的參數列表。表中的第 一個元素是正在被執行的腳本的完整路徑。
# myscript.py
import sys
# 獲取命令行參數
my_args = sys.argv
# my_args 是一個列表,其中的第一個元素是執行的腳本
print(type(my_args))
print(my_args)
如果你只希望保留傳遞到腳本的參數,你可以使用列表切片來選擇除了第一個元素以外的所有參數。
# 使用切片,選擇除第一個以外的所有元素
my_args = sys.argv[1:]
回顧一下上面的R語言例子,所有的參數需要以字符串的形式傳遞,因此有必要轉換為所期望的數據類型。
將輸出結果寫入文件。
通過中間文件共享R和Python之間的數據有幾種選擇。通常,對於普通文本文件,CSVs是很好的表格數據格式,而處理可變長字段或許多嵌套數據結構的非結構化數據(或元數據)形式時,JSON 或YAML是最好的數據格式。
這些都是很常見的數據序列化格式,在R和Python中已存在相應的語法解析器。
在R語言中推薦下面的程序包:
● 對於CSV文件,使用readr
● 對於JSON文件,使用jsonlite
● 對於YAML文件,使用yaml
Python中推薦:
○ 對於CSV文件,使用csv
○ 對於JSON文件,使用json
○ 對於YAML文件,使用PyYAML
csv 和json模塊是Python標准的庫文件,是Python內置模塊,而PyYAML需要額外安裝程序包。所有的R程序包均需要安裝。
總結
R和Python之間的數據傳遞可以通過單一傳遞途徑進行:
△使用命令行傳遞參數
△使用常見的結構化文本文件傳遞數據
然而,在某些實例中,需要將文本文件作為中間文件存儲在本地,這不僅很麻煩而且還影響性能。接下來,我們將討論如何在R和Python中直接調用並在內存中輸出。
命令行執行和執行子進程
為了更好地理解在執行子進程的時候發生了什么,值得重新考慮當命令行運行一個Python 或 R進程中更多的細節。在運行下面的命令時,啟動了一個新的 Python 進程執行該腳本。
在執行過程中,任何被輸出到標准輸出和標准錯誤流的數據會返回到控制台顯示。最常見的實現方式是通過Python中的一個內置函數print()或 是 R中的函數 cat()和 print(),它們將給定字符串的寫入標准輸出流。一旦腳本執行完畢,Python進程隨即關閉。
在這種方式下運行命令行腳本是有用的,但如果希望用這個方法執行多個連續卻相互獨立腳本時,就變得繁瑣,並且容易出錯。然而,這可能讓一個 Python或R進程直接去執行另一個類似的命令。這樣有好處,即從一個Python父進程啟動一個R中的子進程去運行特定的腳本,進而完成分析。一旦R 腳本運行完畢,R中子進程的輸出不是被傳到控制台,而是返回到父進程中。使用這種方法除去了手動單獨執行命令行的步驟。
為了說明一個進程的執行是由另一個進程引起的,我們將會用兩個簡單的例子:一個是Python調用R,另一個是R調用Python。我們人為降低了每個案例中分析結果的重要性,以便把重點放在機器是如何的實現的過程上。
R腳本范例
我們簡單的R腳本例子要從命令行獲取一系列數字並返回最大值。
# max.R
# 獲取命令行參數
myArgs <- commandArgs(trailingOnly = TRUE)
# 轉換成數字類型
nums = as.numeric(myArgs)
# cat將把結果寫入標准輸出流
cat(max(nums))
在Python中執行R腳本
我們需要利用子進程的模塊,也就是標准庫的一部分,來實現從Python中進行調用。我們將使用函數check_output 來調用 R 腳本,執行命令並存儲標准輸出的結果。
想要在Python中調用R來執行 max.R腳本,首先要建立要運行的命令。在Python中的形式以一個字符串列表表示,其相應的元素如下所示:[‘’, ‘’, ‘arg1’ , ‘arg2’, ‘arg3’, ‘arg4’]
下面代碼是運行在Python中調用R的一個例子:
# run_max.py
import subprocess
# 定義命令和參數
command = ‘Rscript’
path2script = ‘path/to your script/max.R’
# args變量的值是一個列表
args = [’11’, ‘3’, ‘9’, ’42’]
#建立子進程命令
cmd = [command, path2script] + args
# check_output會執行命令並存儲結果
x = subprocess.check_output(cmd, universal_newlines=True)
print(‘The maximum of the numbers is:’, x)
參數 universal_newlines=True 告訴 Python 把返回的輸出結果解釋為文本字符串,並處理 Windows 和 Linux 的換行字符。如果省略了這個,則輸出結果會被作為一個字節的字符串返回,同時在進行任何字符串進一步操作之前必須調用x.decode()來解碼成文本。
Python腳本范例
在我們簡單的 Python 腳本中,我們將給定的字符串(第一個參數)拆分為基於所提供的字符串模式的多個子字符串 (第二個參數)。然后,結果以每行一個子字符串的形式輸出到控制台。
# splitstr.py
import sys
# 獲取傳入的參數
string = sys.argv[1]
pattern = sys.argv[2]
#執行分割
ans = string.split(pattern)
#把所產生的元素列表合成一個新命令行
# 分割字符串並打印
print(‘\n’.join(ans))
在R中調用Python
當用R執行子進程時,建議使用 R 的system2函數來執行並獲取輸出。這是因為內置的系統函數跨平台不兼容,非常難使用。
建立要執行的命令是類似於上面的 Python 例子,然而system2 期望命令根據它的參數被分解開來。此外,這些參數首先必須總是正在執行的腳本的路徑。
最后一個困難可能是R腳本路徑名稱中的空格處理引起的。解決這一問題最簡單的方法是為全路徑名稱加上雙引號,然后用單引號封裝此字符串,這樣,R保留參數本身的雙引號。
下面的代碼中,給出在R 中執行 Python 腳本的實例。
# run_splitstr.R
command = “python”
#注意在字符串中的單引號和雙引號(如果路徑名中有空格,這是必須的)
path2script='”path/to your script/splitstr.py”‘
# 設置args成向量
string = “3523462—12413415—4577678—7967956—5456439”
pattern = “—”
args = c(string, pattern)
# 把腳本路徑加入,成為第一個arg參數
allArgs = c(path2script, args)
output = system2(command, args=allArgs, stdout=TRUE)
print(paste(“The Substrings are:\n”, output))
為了獲取標准輸出中的特征向量(每個元素一行),stdout=TRUE 必須在system2中具體說明,不然返回的只是退出狀態。當stdout=TRUE時,退出狀態存儲在一個名為“狀態”的屬性中。
通過子進程調用,可以將Python和R整合到一個應用程序中。這允許一個父進程調用另一個進程作為子進程,並獲取任何輸出到標准輸出的結果。
來源:大數據文摘
