help(os.system)
#os.system(command):該方法在調用完shell腳本后,返回一個16位的二進制數,
#低位為殺死所調用腳本的信號號碼,高位為腳本的退出狀態碼,
#即腳本中exit 1的代碼執行后,os.system函數返回值的高位數則是1,如果低位數是0的情況下,
#則函數的返回值是0x0100,換算為十進制得到256。
#要獲得os.system的正確返回值,可以使用位移運算(將返回值右移8位)還原返回值:
>>> import os
>>> os.system("./test.sh")
hello python!
hello world!
256
>>> n>>8
1
help(os.system)
#os.popen(command):這種調用方式是通過管道的方式來實現,函數返回一個file對象,
#里面的內容是腳本輸出的內容(可簡單理解為echo輸出的內容),使用os.popen調用test.sh的情況
>> import os
>>> os.popen("./test.sh")
<open file './test.sh', mode 'r' at 0x7f6cbbbee4b0>
>>> f=os.popen("./test.sh")
>>> f
<open file './test.sh', mode 'r' at 0x7f6cbbbee540>
>>> f.readlines()
['hello python!\n', 'hello world!\n']
(1)commands.getstatusoutput(cmd),其以字符串的形式返回的是輸出結果和狀態碼,即(status,output)。
(2)commands.getoutput(cmd),返回cmd的輸出結果。
(3)commands.getstatus(file),返回ls -l file的執行結果字符串,調用了getoutput,不建議使用此方法
subprocess模塊,允許創建很多子進程,創建的時候能指定子進程和子進程的輸入、輸出、錯誤輸出管道,執行后能獲取輸出結果和執行狀態。
(1)subprocess.run():python3.5中新增的函數, 執行指定的命令, 等待命令執行完成后返回一個包含執行結果的CompletedProcess類的實例。
(2)subprocess.call():執行指定的命令, 返回命令執行狀態, 功能類似os.system(cmd)。
(3)subprocess.check_call():python2.5中新增的函數, 執行指定的命令, 如果執行成功則返回狀態碼, 否則拋出異常。
說明:subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
args:表示shell指令,若以字符串形式給出shell指令,如"ls -l “則需要使shell=Ture。否則默認已數組形式表示shell變量,如"ls”,"-l"。
當使用比較復雜的shell語句時,可以先使用shlex模塊的shlex.split()方法來幫助格式化命令,然后在傳遞給run()方法或Popen。
# Stubs for subprocess
# Based on http://docs.python.org/2/library/subprocess.html and Python 3 stub
from typing import Sequence, Any, Mapping, Callable, Tuple, IO, Union, Optional, List, Text
_FILE=Union[None, int, IO[Any]]
_TXT=Union[bytes, Text]
_CMD=Union[_TXT, Sequence[_TXT]]
_ENV=Union[Mapping[bytes, _TXT], Mapping[Text, _TXT]]
# Same args as Popen.__init__
def call(args: _CMD,
bufsize: int=...,
executable: _TXT=...,
stdin: _FILE=...,
stdout: _FILE=...,
stderr: _FILE=...,
preexec_fn: Callable[[], Any]=...,
close_fds: bool=...,
shell: bool=...,
cwd: _TXT=...,
env: _ENV=...,
universal_newlines: bool=...,
startupinfo: Any=...,
creationflags: int=...) -> int: ...
def check_call(args: _CMD,
bufsize: int=...,
executable: _TXT=...,
stdin: _FILE=...,
stdout: _FILE=...,
stderr: _FILE=...,
preexec_fn: Callable[[], Any]=...,
close_fds: bool=...,
shell: bool=...,
cwd: _TXT=...,
env: _ENV=...,
universal_newlines: bool=...,
startupinfo: Any=...,
creationflags: int=...) -> int: ...
# Same args as Popen.__init__ except for stdout
def check_output(args: _CMD,
bufsize: int=...,
executable: _TXT=...,
stdin: _FILE=...,
stderr: _FILE=...,
preexec_fn: Callable[[], Any]=...,
close_fds: bool=...,
shell: bool=...,
cwd: _TXT=...,
env: _ENV=...,
universal_newlines: bool=...,
startupinfo: Any=...,
creationflags: int=...) -> bytes: ...
PIPE=... # type: int
STDOUT=... # type: int
class CalledProcessError(Exception):
returncode=0
# morally: _CMD
cmd=... # type: Any
# morally: Optional[bytes]
output=... # type: Any
def __init__(self,
returncode: int,
cmd: _CMD,
output: Optional[bytes]=...) -> None: ...
class Popen:
stdin=... # type: Optional[IO[Any]]
stdout=... # type: Optional[IO[Any]]
stderr=... # type: Optional[IO[Any]]
pid=0
returncode=0
def __init__(self,
args: _CMD,
bufsize: int=...,
executable: Optional[_TXT]=...,
stdin: Optional[_FILE]=...,
stdout: Optional[_FILE]=...,
stderr: Optional[_FILE]=...,
preexec_fn: Optional[Callable[[], Any]]=...,
close_fds: bool=...,
shell: bool=...,
cwd: Optional[_TXT]=...,
env: Optional[_ENV]=...,
universal_newlines: bool=...,
startupinfo: Optional[Any]=...,
creationflags: int=...) -> None: ...
def poll(self) -> int: ...
def wait(self) -> int: ...
# morally: -> Tuple[Optional[bytes], Optional[bytes]]
def communicate(self, input: Optional[_TXT]=...) -> Tuple[Any, Any]: ...
def send_signal(self, signal: int) -> None: ...
def terminate(self) -> None: ...
def kill(self) -> None: ...
def __enter__(self) -> 'Popen': ...
def __exit__(self, type, value, traceback) -> bool: ...
# Windows-only: STARTUPINFO etc.
STD_INPUT_HANDLE=... # type: Any
STD_OUTPUT_HANDLE=... # type: Any
STD_ERROR_HANDLE=... # type: Any
SW_HIDE=... # type: Any
STARTF_USESTDHANDLES=... # type: Any
STARTF_USESHOWWINDOW=... # type: Any
CREATE_NEW_CONSOLE=... # type: Any
CREATE_NEW_PROCESS_GROUP=... # type: Any
https://www.jb51.net/article/186301.htm
這里在樹莓派下使用HTML網頁和輕量級web服務器Lighttpd直接調用python或者bash腳本,而并不使用Django,Flask等Web框架。
這里我們實現通過網頁端對一個LED燈進行點亮和關閉操作
第一步: 需要的硬件材料
第二步:安裝Lighttpd輕量級web 服務器
Lighttpd是一個輕量級的WEB服務器,安全,快速,靈活,占用極低的內存,適合樹莓派這樣的ARM架構的設備使用,類似的其他服務器還有Apache,Nginx等。我們將使用Lightttpd 的CGI技術來調用腳本。
安裝Lightttpd:
使用systemctl status lighttpd可以看到lighttp的已經開始運行
對lighttpd進行配置:
啟用cgi和fastcgi,我們將會借助cgi技術實現http網頁調用樹莓派下的腳本
sudo lighttpd-enable-mod cgi
sudo lighttpd-enable-mod fastcgi
CGI是Common Gateway Interface ,是web服務器調用服務器腳本常使用的技術
默認的lighttpd的配置文件的路徑是:
/etc/lighttpd
在lighttpd.conf中可以對服務器的站點路徑 ,端口等進行配置,這里我們使用默認的站點路徑/var/www/html
配置cgi:
打開/etc/lighttpd/conf-enabled/10-cig.conf 修改為如下的配置
# /usr/share/doc/lighttpd/cgi.txt
server.modules +=( "mod_cgi" )
$HTTP["url"]=~ "^/cgi-bin/" {
alias.url +=( "/cgi-bin/"=> "/var/www/html/cgi-bin/" )
cgi.assign=(".cgi"=> "/usr/bin/bash",".py"=> "/usr/bin/python3")
}
其中alias.url +=( "/cgi-bin/"=> "/var/www/html/cgi-bin/" ) 制定了cgi尋找的路徑實在
/var/www/html/cgi-bin/,因此在/var/www/html/文件夾下新建cgi-bin文件夾
sudo mkdir /var/www/html/
配置文件中cgi.assign=(".cgi"=> "/usr/bin/bash",".py"=> "/usr/bin/python3") ,是說
.py 的腳本使用python3來執行,.cgi的腳本這里我們定義為bash腳本,類似的你可以定義perl腳本等。
第三步:創建腳本
樹莓派下默認安裝了WringPi,可以對樹莓派的GPIO進行操作,這里我們使用第12引腳進行led的操作
在/var/www/html/cgi-bin目錄下新建ledon.cgi和ledoff.cgi兩個腳本
cd /var/www/html/cgi-bin
touch ledon.cgi ledon.cgi
chmod 755 ./ledon.cgi ./ledon.cgi
ledon.cgi實現點亮led,內容為
#!/bin/bash
gpio -g mode 18 out
gpio -g write 18 0
ledon.cgi實現關閉led ,內容為
#!/bin/bash
gpio -g mode 18 out
gpio -g write 18 1
創建一個python腳本test.py
print("Content-Type: text/html\n\n")
timeStr=time.strftime("%c") # obtains current time
htmlFormat="""
<html>
<Title>The Time Now</Title>
<body>
<p>The current Central date and time is:</p>
</body>
</html> """
print(htmlFormat+str(timeStr))
注意這里如果需要使用python代碼操作gpio等外圍硬件,會因為lighttpd默認用戶www-data的權限問題無法成功,需要將lighttpd的用戶修改為用戶pi
我們這里使用bash腳本操作led等,python腳本返回數據不存在權限問題
第四步:創建HTML網頁調用腳本
在路徑/var/www/html/下新建index.html
cd /var/www/html/
sudo touch index.html
sudo chmod 777 index.html
index.html 的內容如下
<!DOCTYPE html>
<html>
<head>
<title>Welcome You!</title>
<style>
body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
</style>
</head>
<body>
<h1>Welcome to lighttpd!</h1>
<button style="height: 50px; width: 100px" onclick="lighton()">ledon</button>
<button style="height: 50px; width: 100px" onclick="lightoff()">ledoff</button>
<button style="height: 50px; width: 100px" onclick="pythondata()">pythondata</button>
<br><br>
<script>
var xmlhttp;
xmlhttp=new XMLHttpRequest();
function lighton()
{
xmlhttp.open("GET","cgi-bin/ledon.cgi",true);
xmlhttp.send();
}
function lightoff()
{
xmlhttp.open("GET","cgi-bin/ledoff.cgi",true);
xmlhttp.send();
}
function pythondata()
{
xmlhttp.open("GET","cgi-bin/test.py",true);
xmlhttp.send();
xmlhttp.onload=function(e) {
if(this.status==200||this.status==304){
alert(this.responseText);
}
};
}
</script>
這里通過XMLHttpRequest 實現原生GET請求,XMLHttpRequest一開始只是微軟瀏覽器提供的一個接口,后來各大瀏覽器紛紛效仿也提供了這個接口,再后來W3C對它進行了標準化,提出了XMLHttpRequest標準。