scala VS python2 (linux or shell)


PS:只考慮最新版的scala和python2.x,由於python3.x和python2.x區別比較大,而且主流的一些開源項目都用的python2,目前python2一點點在兼容python3

1.安裝

PS:python2和scala的安裝都很簡單

(1)python->

到官網下載相應的版本http://www.python.org/ftp/python/

 以Python-2.6.6為例

解壓 tar xvzf Python-2.6.6.tgz
     cd Python-2.6.6

編譯安裝python
./configure –prefix=/usr/local/python2.6
make
make install

創建一個python的鏈接
ln -sf /usr/local/python/bin/python2.6 /usr/bin/python

python -V 顯示版本信息

Python 2.6.6

(2)scala

官網下載相應版本 http://www.scala-lang.org/download/all.html 以scala-2.10.4為例

解壓 tar xvzf scala-2.10.4.tgz

配置環境變量

export SCALA_HOME=/usr/scala/scala-2.10.3

export PATH=$PATH:$SCALA_HOME/bin

scala -version 顯示版本信息

 Scala code runner version 2.10.4 -- Copyright 2002-2013, LAMP/EPFL

2.python scala 調用相同的linux和shell命令對比

(1)python的功能是按照模塊划分,調用linux命令有三種方式,及三個模塊可以使用

    一,os 模塊

import os

#system方法 會創建子進程運行外部程序,方法只返回外部程序的運行結果。這個方法比較適用於外部程序沒有輸出結果的情況。
os.system("echo \"Hello World\"")
Hello World #直接打印命令信息
0 #命令正常返回值

# 使用val接收返回值
val = os.system("ls -lt | grep \"test\"")  #輸出信息
print val
256 #調用一個沒有返回結果的命令返回256 有返回結果返回0
#popen方法 當需要得到外部程序的輸出結果時,本方法非常有用,返回一個類文件對象,調用該對象的read()或readlines()方法可以讀取輸出內容

os.popen('ls -lt') #不能輸出命令信息,返回對象
print os.popen('ls -lt').read() #調用read()方法輸出命令信息


 

  

    二,commands 模塊

 

import commands

commands模塊的getoutput方法,同popen的區別是一個返回類文件對象,而getoutput將外部程序的輸出結果當作字符串返回
#commands.getstatusoutput(cmd)        返回(status, output)
#commands.getoutput(cmd)              只返回輸出結果
#commands.getstatus(file)             返回ls -ld file的執行結果字符串,調用了getoutput
#---------------------------------------------------
commands.getstatusoutput('ls -lt')
commands.getoutput('ls -lt')
commands.getstatus('ls -lt')

 

  三,subprocess 模塊  啟動一個新的進程並且與之通信

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions: os.system os.spawn* os.popen* popen2.* commands.*

PS:官網說該模塊意在替換那些舊的模塊,包括上邊描述的兩個模塊

import subprocess

subprocess.Popen(
args, #可以是字符串或者序列類型(如:list,元組),用於指定進程的可執行文件及其參數。如果是序列類型,第一個元素通常是可執行文件的路徑。我們也可以顯式的使用executeable參數來指定可執行文件的路徑。
bufsize=0,#指定緩沖。0 無緩沖,1 行緩沖,其他 緩沖區大小,負值 系統緩沖(全緩沖)
executable=None,
stdin=None,#分別表示程序的標准輸入、輸出、錯誤句柄。他們可以是PIPE,文件描述符或文件對象,也可以設置為None,表示從父進程繼承。
stdout=None,
stderr=None,
preexec_fn=None,#只在Unix平台下有效,用於指定一個可執行對象(callable object),它將在子進程運行之前被調用。
close_fds=False,#在windows平台下,如果close_fds被設置為True,則新創建的子進程將不會繼承父進程的輸入、輸出、錯誤管道。我們不能將close_fds設置為True同時重定向子進程的標准輸入、輸出與錯誤(stdin, stdout, stderr)。
shell=False,#設為true,程序將通過shell來執行。
cwd=None,#用於設置子進程的當前目錄
env=None,#是字典類型,用於指定子進程的環境變量。如果env = None,子進程的環境變量將從父進程中繼承
universal_newlines=False,#不同操作系統下,文本的換行符是不一樣的。如:windows下用'/r/n'表示換,而Linux下用'/n'。如果將此參數設置為 True,Python統一把這些換行符當作'/n'來處理。startupinfo與createionflags只在windows下用效,它們將被 傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等。
startupinfo=None,#startupinfo與createionflags只在windows下有效,它們將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等。
creationflags=0
)

#Popen方法

#1)、Popen.poll():用於檢查子進程是否已經結束。設置並返回returncode屬性。

#2)、Popen.wait():等待子進程結束。設置並返回returncode屬性。

#3)、Popen.communicate(input=None):與子進程進行交互。向stdin發送數 據,或從stdout和stderr中讀取數據。可選參數input指定發送到子進程的參數。Communicate()返回一個元組: (stdoutdata, stderrdata)。注意:如果希望通過進程的stdin向其發送數據,在創建Popen對象的時候,參數stdin必須被設置為PIPE。同樣,如 果希望從stdout和stderr獲取數據,必須將stdout和stderr設置為PIPE。

#4)、Popen.send_signal(signal):向子進程發送信號。

#5)、Popen.terminate():停止(stop)子進程。在windows平台下,該方法將調用Windows API TerminateProcess()來結束子進程。

#6)、Popen.kill():殺死子進程。

#7)、Popen.stdin:如果在創建Popen對象是,參數stdin被設置為PIPE,Popen.stdin將返回一個文件對象用於策子進程發送指令。否則返回None。

#8)、Popen.stdout:如果在創建Popen對象是,參數stdout被設置為PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。否則返回None。

#9)、Popen.stderr:如果在創建Popen對象是,參數stdout被設置為PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。否則返回None。

#10)、Popen.pid:獲取子進程的進程ID。

#11)、Popen.returncode:獲取進程的返回值。如果進程還沒有結束,返回None。

#12)、subprocess.call(*popenargs, **kwargs):運行命令。該函數將一直等待到子進程運行結束,並返回進程的returncode。如果子進程不需要進行交互,就可以使用該函數來創建。

#13)、subprocess.check_call(*popenargs, **kwargs):與subprocess.call(*popenargs, **kwargs)功能一樣,只是如果子進程返回的returncode不為0的話,將觸發CalledProcessError異常。在異常對象中,包括進程的returncode信息。

retcode = subprocess.call(["ls", "-lt"])
#輸出信息
print retcode
0 #有返回值
#也可以用如下方式
retcode = subprocess.check_call(["ls", "-l"])
print retcode

#腳本內容 sunxu.sh
#!/bin/sh

sbin="`dirname "$0"`"
echo "\$0=$0"
echo "\$1=$1"
echo "sbin=$sbin"
sbin="`cd "$sbin"; pwd`"
echo "sbin=$sbin"
echo ${BASH_SOURCE[0]}
echo "${BASH_SOURCE:-$0}"

#調用腳本
subprocess.Popen('/opt/users/sunxu/sunxu.sh', shell=True) #或者
subprocess.call('/opt/users/sunxu/sunxu.sh', shell=True)

#兩者的區別是前者無阻塞,會和主程序並行運行,后者必須等待命令執行完畢,如果想要前者編程阻塞可以這樣
  s = subprocess.Popen('/opt/users/sunxu/sunxu.sh', shell=True)
  s.wait()
 
#程序返回運行結果 它會返回一個元組:(stdoutdata, stderrdata)
s = subprocess.Popen(' /opt/users/sunxu/sunxu.sh', shell=True, stdout=subprocess.PIPE)
s.communicate()
('$0=/opt/users/sunxu/sunxu.sh\n$1=\nsbin=/opt/users/sunxu\nsbin=/opt/users/sunxu\n/opt/users/sunxu/sunxu.sh\n/opt/users/sunxu/sunxu.sh\n', None)
 
#subprocess還有另一種更簡單方法,效果一樣,它會返回stdout  版本>2.6 否則報錯 :AttributeError: 'module' object has no attribute 'check_output'
s = subprocess.check_output(' /opt/users/sunxu/sunxu.sh', shell=True)
s
('$0=/opt/users/sunxu/sunxu.sh\n$1=\nsbin=/opt/users/sunxu\nsbin=/opt/users/sunxu\n/opt/users/sunxu/sunxu.sh\n/opt/users/sunxu/sunxu.sh\n', None)
 
 
#subprocess.PIPE實際上為文本流提供一個緩存區。直到communicate()方法從PIPE中讀取出PIPE中的文本.要注意的是,communicate()是Popen對象的一個方法,該方法會阻塞父進程,直到子進程完成。
child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
out = child2.communicate()
print out
#流程如下
child1.stdout-->subprocess.PIPE
child2.stdin<--subprocess.PIPE
child2.stdout-->subprocess.PIPE
 
child.poll()# 檢查子進程狀態
child.kill()# 終止子進程
child.send_signal()# 向子進程發送信號
child.terminate() # 終止子進程

 

 

 

(2)scala已經把功能封裝在scala.sys.process 引用之后可以直接使用,里邊包含很多隱式的方法可以調用

  

import scala.sys.process._

#理解下面的命令就明白process的用法了
"ls" #| "grep .scala" #&& Seq("sh", "-c", "scalac *.scala") #|| "echo nothing found" lines

#使用!結尾表示使用外部命令
"ls -lt"!
#管道不能在命令中直接使用 例如:"ls -lt | grep test" 正確做法
"ls -lt" #| "grep test"!

腳本內容 sunxu.sh
#!/bin/sh
echo "hello world"

"sh /opt/test/sunxu.sh"!
#輸出
hello world

#存儲變量數據 用!!把結果以字符串的形式返回
val result="ls -lt" #| "grep Hood"!!
#輸出
println(result)

#使用邏輯操作 #&& , #|| 格式如下
cmd1 #&& cmd2
cmd1 #|| cmd2
"echo hello" #&& "echo world"!
"echo hello" #|| "echo world"!

#重定向 #< 或者 #>
#eg:把結果重定向到文件中
"ls -al .." #> new java.io.File("output.txt")!
#eg:查詢網頁中的內容
"grep Scala" #< new java.net.URL("http://horstmann.com/index.html")!
#把網頁導成html文件
import java.io.File import java.net.URL new URL("http://www.scala-lang.org/") #> new File("scala-lang.html") !

#追加操作 #>> 或者 #<<
#eg:追加內容到文件尾部
"ls -al .." #>> new java.io.File("output.txt")! 

 

scala官網的幾個列子

  • Return status of the process (! methods)
  • Output of the process as a String (!! methods)
  • Continuous output of the process as a Stream[String] (lines methods)
  • The Process representing it (run methods)
import scala.sys.process._

// This uses ! to get the exit code
def fileExists(name: String) = Seq("test", "-f", name).! == 0

// This uses !! to get the whole result as a string
val dirContents = "ls".!!

// This "fire-and-forgets" the method, which can be lazily read through
// a Stream[String]
def sourceFilesAt(baseDir: String): Stream[String] = {
  val cmd = Seq("find", baseDir, "-name", "*.scala", "-type", "f")
  cmd.lines
}

 

Handling Input and Output

import scala.sys.process._

// An overly complex way of computing size of a compressed file
def gzFileSize(name: String) = {
  val cat = Seq("zcat", name)
  var count = 0
  def byteCounter(input: java.io.InputStream) = {
    while(input.read() != -1) count += 1
    input.close()
  }
  cat ! new ProcessIO(_.close(), byteCounter, _.close())
  count
}

// This "fire-and-forgets" the method, which can be lazily read through
// a Stream[String], and accumulates all errors on a StringBuffer
def sourceFilesAt(baseDir: String): (Stream[String], StringBuffer) = {
  val buffer = new StringBuffer()
  val cmd = Seq("find", baseDir, "-name", "*.scala", "-type", "f")
  val lines = cmd lines_! ProcessLogger(buffer append _)
  (lines, buffer)
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM