直接運(yùn)行 和 模塊運(yùn)行 的區(qū)別
- python xxx.py
- python -m xxx.py
這是兩種加載py文件的方式:
1叫做直接運(yùn)行
2把模塊當(dāng)作腳本來啟動(注意:但是__name__的值為'main' )
直接啟動是把xx.py文件,所在的目錄放到了sys.path屬性中。
模塊啟動是把你輸入命令的目錄(也就是當(dāng)前路徑),放到了sys.path屬性中
下面可以看看例子:
假設(shè)我們項目的結(jié)構(gòu)是這樣的:
statistics
->activity
-> stat.py
->base
->connection.py
->__init__.py
python activity/stat.py
這樣執(zhí)行的話,打印sys.path可以看到sys.path的第一個目錄就是運(yùn)行的stat.py所在的目錄,也就是activity目錄
['/home/lidongwei/vhost/nemu-server/statistics/activity', ...]
那如果我們用模塊運(yùn)行 python -m
python -m activity.mumu_stat
這樣運(yùn)行的話sys.path的第一個值就是'', 也就是當(dāng)前執(zhí)行python的目錄
['', ...]
兩種不同的運(yùn)行,分別有什么場景?
如果我們想在stat.py 里面import activity目錄上一個文件夾的其他模塊是不可以的, 比如我想導(dǎo)入base.connection里面的db_mongo, 這是不可以的,為什么?因為sys.path 就是在activity目錄,根目錄statictis 沒有在sys.path里面啊
from base.connection import db_mongo
這樣會報錯:
ImportError: No module named base.connection
那自然我們就會想能否這樣通過相對路徑引入
from ..base.connection import db_mongo
然后執(zhí)行 python activity/stat.py
這樣還回報錯,但是是另外一個報錯:
ValueError: Attempted relative import in non-package
這是因為, 如果我們直接執(zhí)行py文件的話,是不可以使用相對引入的,否則就會報錯 Attempted relative import in non-package
那如果我們用模塊運(yùn)行會怎樣 python -m
[~/vhost/statistics]$ python -m activity.mumu_stat
報了另外一個錯誤
ValueError: Attempted relative import beyond toplevel package
這是因為 ..base的時候已經(jīng)出了頂級目錄了,為什么?因為python -m 的時候,sys.path的第一個目錄就是當(dāng)前執(zhí)行python的目錄, 也就是 ~/vhost/statistics, 這個已經(jīng)是頂級目錄了, 還要..base的話就會超出,所以報錯
這個時候,到底是使用直接啟動,還是以模塊的啟動?目的就是把import的那個模塊的路徑放到sys.path中。
總結(jié)
導(dǎo)入一個叫 mod1 的模塊時,解釋器先在當(dāng)前目錄中搜索名為 mod1.py 的文件。如果沒有找到的話,接著會到 sys.path 變量中給出的目錄列表中查找。 sys.path 變量的初始值來自如下:
- 輸入腳本的目錄(當(dāng)前目錄)。
- 環(huán)境變量 PYTHONPATH 表示的目錄列表中搜索(這和 shell 變量 PATH 具有一樣的語法,即一系列目錄名的列表)。
- Python 默認(rèn)安裝路徑中搜索。
實際上,解釋器由 sys.path 變量指定的路徑目錄搜索模塊,該變量初始化時默認(rèn)包含了輸入腳本(或者當(dāng)前目錄), PYTHONPATH 和安裝目錄。這樣就允許 Python程序了解如何修改或替換模塊搜索目錄。
PYTHONPATH 與 sys.path的關(guān)系
(mumu-store-server-env) [~/vhost/nemu-statistics]$ echo $PYTHONPATH
(mumu-store-server-env) [~/vhost/nemu-statistics]$ python
>>> import sys
>>> sys.path
['', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/plat-x86_64-linux-gnu', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-tk', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-old', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-dynload', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/home/lidongwei/.virtualenvs/mumu-store-server-env/local/lib/python2.7/site-packages', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/site-packages']
默認(rèn)情況下PYTHONPATH是空的, 然后進(jìn)去看到sys.path是一個列表,包括有所有查找包的目錄
下面我們給PYTHON加個目錄
(mumu-store-server-env) [~/vhost/nemu-statistics]$ export PYTHONPATH=/home/lidongwei/Desktop
(mumu-store-server-env) [~/vhost/nemu-statistics]$ python
>>> import sys
>>> sys.path
['', '/home/lidongwei/Desktop', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/plat-x86_64-linux-gnu', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-tk', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-old', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/lib-dynload', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/home/lidongwei/.virtualenvs/mumu-store-server-env/local/lib/python2.7/site-packages', '/home/lidongwei/.virtualenvs/mumu-store-server-env/lib/python2.7/site-packages']
可以看到'/home/lidongwei/Desktop' 這個目錄已經(jīng)被加到sys.path了, 說明PYTHONPATH會加到sys.path