Ⅰ python怎樣使用解釋器
大學里計算機科學最吸引我的地方就是編譯器。最神奇的是,編譯器是如何讀出我寫的那些爛代碼,並且還能生成那麼復雜的程序。當我終於選了一門編譯方面的課程時,我發現這個過程比我想的要簡單得多。
在本系列的文章中,我會試著通過為一種基本命令語言IMP寫一個解釋器,來展示這種簡易性。因為IMP是一個簡單廣為人知的語言,所以打算用 Python寫這個解釋器。Python代碼看起來很像偽代碼,所以即使你不認識 Python,你也能理解它。解析可以通過一套從頭開始實現的解析器組合完成(在本系列的下一篇文章中會有解釋)。除了sys(用於I/O)、re(用於解析正則表達式)以及unittest(用於確保一切工作正常)庫,沒有使用其他額外的庫。
IMP 語言
在開始寫之前,我們先來討論一下將要解釋的語言。IMP是擁有下面結構的最小命令語言:
賦值語句(所有變數都是全局的,而且只能存儲整數):
Python
1
x := 1
條件語句:
Python
1
2
3
4
5
if x = 1 then
y := 2
else
y := 3
end
while循環:
Python
1
2
3
while x < 10 do
x := x + 1
end
復合語句(分號分隔):
Python
1
2
x := 1;
y := 2
OK,所以它只是一門工具語言,但你可以很容易就把它擴展成比Lua或python更有用的語言。我希望能把這份教程能保持盡量簡單。
下面這個例子是計算階乘的程序:
Python
1
2
3
4
5
6
n := 5;
p := 1;
while n > 0 do
p := p * n;
n := n - 1
end
IMP沒有讀取輸入的方式,所以初始狀態必須是在程序最開始寫一系列的賦值語句。也沒有列印結果的方式,所以解釋器必須在程序的結尾列印所有變數的值。
解釋器的結構
解釋器的核心是「中間表示」(Intermediate representation,IR)。這就是如何在內存中表示IMP程序。因為IMP是一個很簡單的語言,中間表示將直接對應於語言的語法;每一種表達和語句都有對應的類。在一種更復雜的語言中,你不僅需要一個「語法表示」,還需要一個更容易分析或運行的「語義表示」。
解釋器將會執行三個階段:
將源碼中的字元分割成標記符(token)
將標記符組織成一棵抽象語法樹(AST)。抽象語法樹就是中間表示。
評估這棵抽象語法樹,並在最後列印這棵樹的狀態
將字元串分割成標記符的過程叫做「詞法分析」,通過一個詞法分析器完成。關鍵字是很短,易於理解的字元串,包含程序中最基本的部分,如數字、標識符、關鍵字和操作符。詞法分析器會除去空格和注釋,因為它們都會被解釋器忽略。
實際執行這個解析過的抽象語法樹的過程稱為評估。這實際上是這個解析器中最簡單的部分了。
本文會把重點放在詞法分析器上。我們將編寫一個通用的詞彙庫,然後用它來為IMP創建一個詞法分析器。下一篇文章將會重點打造一個語法分析器和評估計算器。
詞彙庫
詞法分析器的操作相當簡單。它是基於正則表達式的,所以如果你不熟悉它們,你可能需要讀一些資料。簡單來說,正則表達式就是一種能描述其他字元串的特殊的格式化的字元串。你可以使用它們去匹配電話號碼或是郵箱地址,或者是像我們遇到在這種情況,不同類型的標記符。
詞法分析器的輸入可能只是一個字元串。簡單起見,我們將整個輸入文件都讀到內存中。輸出是一個標記符列表。每個標記符包括一個值(它代表的字元串)和一個標記(表示它是一個什麼類型的標記符)。語法分析器會使用這兩個數據來決定如何構建一棵抽象語法樹。
由於不論何種語言的詞法分析器,其操作都大同小異,我們將創建一個通用的詞法分析器,包括一個正則表達式列表和對應的標簽(tag)。對每一個表達式,它都會檢查是否和當前位置的輸入文本匹配。如果匹配,匹配文本就會作為一個標記符被提取出來,並且被加上該正則表達式的標簽。如果該正則表達式沒有標簽,那麼這段文本將會被丟棄。這樣免得我們被諸如注釋和空格之類的垃圾字元干擾。如果沒有匹配的正則表達式,程序就要報錯並終止。這個過程會不斷循環直到沒有字元可匹配。
下面是一段來自詞彙庫的代碼:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sys
import re
def lex(characters, token_exprs):
pos = 0
tokens = []
while pos < len(characters):
match = None
for token_expr in token_exprs:
pattern, tag = token_expr
regex = re.compile(pattern)
match = regex.match(characters, pos)
if match:
text = match.group(0)
if tag:
token = (text, tag)
tokens.append(token)
break
if not match:
sys.stderr.write('Illegal character: %sn' % characters[pos])
sys.exit(1)
else:
pos = match.end(0)
return tokens
注意,我們遍歷正則表達式的順序很重要。lex會遍歷所有的表達式,然後接受第一個匹配成功的表達式。這也就意味著,當使用詞法分析器時,我們應當首先考慮最具體的表達式(像那些匹配運算元(matching operator)和關鍵詞),其次才是比較一般的表達式(像標識符和數字)。
詞法分析器
給定上面的lex函數,為IMP定義一個詞法分析器就非常簡單了。首先我們要做的就是為標記符定義一系列的標簽。IMP只需要三個標簽。RESERVED表示一個保留字或操作符。INT表示一個文字整數。ID代表標識符。
Python
1
2
3
4
5
import lexer
RESERVED = 'RESERVED'
INT= 'INT'
ID = 'ID'
接下來定義詞法分析器將會用到的標記符表達式。前兩個表達式匹配空格和注釋。它們沒有標簽,所以 lex 會丟棄它們匹配到的所有字元。
Python
1
2
3
token_exprs = [
(r'[ nt]+',None),
(r'#[^n]*', None),
然後,只剩下所有的操作符和保留字了。記住,每個正則表達式前面的「r」表示這個字元串是「raw」;Python不會處理任何轉義字元。這使我們可以在字元串中包含進反斜線,正則表達式正是利用這一點來轉義操作符比如「+」和「*」。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(r':=', RESERVED),
(r'(',RESERVED),
(r')',RESERVED),
(r';', RESERVED),
(r'+',RESERVED),
(r'-', RESERVED),
(r'*',RESERVED),
(r'/', RESERVED),
(r'<=',RESERVED),
(r'<', RESERVED),
(r'>=',RESERVED),
(r'>', RESERVED),
(r'=', RESERVED),
(r'!=',RESERVED),
(r'and', RESERVED),
(r'or',RESERVED),
(r'not', RESERVED),
(r'if',RESERVED),
(r'then',RESERVED),
(r'else',RESERVED),
(r'while', RESERVED),
(r'do',RESERVED),
(r'end', RESERVED),
最後,輪到整數和標識符的表達式。要注意的是,標識符的正則表達式會匹配上面的所有的保留字,所以它一定要留到最後。
Python
1
2
3
(r'[0-9]+',INT),
(r'[A-Za-z][A-Za-z0-9_]*', ID),
]
既然正則表達式已經定義好了,我們還需要創建一個實際的lexer函數。
Python
1
2
def imp_lex(characters):
return lexer.lex(characters, token_exprs)
如果你對這部分感興趣,這里有一些驅動代碼可以測試輸出:
Python
1
2
3
4
5
6
7
8
9
10
11
import sys
from imp_lexer import *
if __name__ == '__main__':
filename = sys.argv[1]
file = open(filename)
characters = file.read()
file.close()
tokens = imp_lex(characters)
for token in tokens:
print token
繼續……
在本系列的下一篇文章中,我會討論解析器組合,然後描述如何使用他們從lexer中生成的標記符列表建立抽象語法樹。
如果你對於實現IMP解釋器很感興趣,你可以從這里下載全部的源碼。
在源碼包含的示例文件中運行解釋器:
Python
1
python imp.py hello.imp
運行單元測試:
Python
1
python test.py
Ⅱ 如何python3中調用python2中的方法
在Windows操作系統上,Python一般被安裝在C:Pythonxx的位置,這里xx代表版本號,例如,Python3.4就被安裝在C:Python34文件夾中。你只需要把C:Pythonxx加入到系統環境變數中的path變數中,就可以從任何位置調用python解釋器了。
OK,打開命令行窗口,輸入python,就可以調用python解釋器了。
要退出解釋器,可以輸入exit()函數或者quit()函數。
當然,還有另外一種方式調用python解釋器直接解釋執行Python語句,格式:python -c command [arg] ...,這里command就是要執行的python語句。
有一些腳本很有用,也可以直接作為模塊來運行,格式: python -m mole [arg] ...,其中mole就是要運行的模塊名字,當然這個模塊必須要能夠被Python運行時環境找到,也就是說它必須能夠被import到,換句話說,相當於運行了import mole.
Ⅲ python3中,用os.system運行一個python2的程序(該程序調用一些模塊),結果好像是調用了python3模塊出錯
環境變數裡面設置的python3的路徑,所以os調用的時候啟動的python3,具體可以在命令行輸入python --version看下版本號
Ⅳ python新手求解python2和python3的問題
python中python2和python3之間的轉換方式如下:
一、放棄python 2.6之前的python版本
python 2.6之前的python版本缺少一些新特性,會給你的遷移工作帶來不少麻煩。如果不是迫不得已還是放棄對之前版本的支持吧。
二、使用 2to3 工具對代碼進行檢查和轉換
2to3是python自帶的一個代碼轉換工具,可以將python2的代碼自動轉換為python3的代碼。當然,不幸的是轉換出的代碼並沒有對python2的兼容做任何的處理。所以我們並不真正使用2to3轉換出的代碼。執行2to3.py 查看輸出信息,並修正相關問題。為了簡化這個轉換過程,這個腳本會將你的Python 2程序源文件作為輸入,然後自動將其轉換到Python 3的形式。
Ⅳ python3中使用部分python2中的一些代碼報錯怎樣解決
Python 3中的str類型對象有點像Python 2中的unicode。
Python 3中的str是未編碼的,str有一個encode方法,調用這個方法後將產生一個編碼後的byte類型的字元串(這有點像Python 2中的str)。而byte類型的字元串支持解碼操作。
Ⅵ 電腦已經裝了python3,怎麼兼容2
由於歷史原因,Python有兩個大的版本分支,Python2和Python3,又由於一些庫只支持某個版本分支,所以需要在電腦上同時安裝Python2和Python3,因此如何讓兩個版本的Python兼容,如何讓腳本在對應的Python版本上運行,這個是值得總結的。
對於Ubuntu 16.04 LTS版本來說,Python2(2.7.12)和Python3(3.5.2)默認同時安裝,默認的python版本是2.7.12。
當python腳本需要python2運行時,只需在腳本前加上,然後運行py xxx.py即可。
#! python2
當python腳本需要python3運行時,只需在腳本前加上,,然後運行py xxx.py即可。
#! python3
就這么簡單。
同時,這也完美解決了在pip在python2和python3共存的環境下報錯,提示Fatal error in launcher: Unable to create process using '"'的問題。
當需要python2的pip時,只需
py -2 -m pip install xxx
當需要python3的pip時,只需
py -3 -m pip install xxx
python2和python3的pip package就這樣可以完美分開了。
Ⅶ pycharm編譯python3為什麼不能直接計算數學結果
剛開始是這樣,筆者在PyCharm新建了一個package,然後放了一個腳本
Ⅷ 如何在安裝pip3以及第三方python庫
環境
OS:10.12.3 (16D32) macOS Sierra1
2
3
什麼是pip
Python之所以強大,其中一個原因是其豐富的第三方庫。pip則是python第三方庫的包管理工具。1
2
3
如何安裝pip3
如果通過homebrew安裝python3,那麼pip3會同時安裝。所以建議直接通過homebrew安裝python3:1
2
https://pip.readthedocs.io/en/stable/installing/
https://bootstrap.pypa.io/get-pip.py
再次執行上述命令,顯示:
安裝成功
如何安裝第三方庫
有了pip3以後,安裝第三方庫就容易多了,比如:1
2
Ⅸ 怎麼啟動python解釋器
1.首先找到本地python安裝位置,若找不到可直接搜索「python」,復制「python.exe」執行文件的所在目錄,如下:
注意事項:
python2.x下為:print "Hello World"
python3.x下print需要加「()」:print ("Hello World")
Ⅹ python3解釋器執行 d = {1:1,2:1}後查看d的結果是__
{1: 1, 2: 1}