很基礎很重要的一課,雖然很簡單,但是防止以后忘了,還是記下來
這個筆記里說的都是import本地的,自己創建的,或者復制粘貼的別人的,總之“不是安裝到library”的module or package, 所以標題里有個大寫的LOCAL
module
what’s a module ?
It’s just a python filewhy do we need?
Because we wanna re-use code, your own code or someone others’dir() 用於在Python interpreter shell中展示當前的namespace,namespace這個詞真是好久不見
import LOCAL module
print name會打印這個.py文件的名字
➜ Desktop pwd
/Users/harry/Desktop
➜ Desktop more test_function.py
print __name__
a = 100
def some_func():
print "hello"
print "world"
print a
➜ Desktop
這個例子是引入本地的某個module,module其實是一個.py文件,所以這個例子一定要在同一個目錄下做,我選了Desktop目錄
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_function # 第一種方式,直接寫名字
test_function
>>># 每次引入一個module,你當前的Python interpreter都會把這個module的代碼逐行執行,所以這里有一個test_function的輸出,因為源文件里有個 print __name__
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'test_function']
>>>
>>> test_function.some_func()
hello
world
100
>>> test_function.b = 77 # 注意這個地方,雖然原來的test_function.py里沒有這個叫b的變量,但是其實可以給它賦值
>>>
>>> test_function.b
77
>>>
>>> from test_function import some_func
>>>
>>> some_func()
hello
world
100
>>> dir() # 這次的namespace里就會多了這個some_func()
['__builtins__', '__doc__', '__name__', '__package__', 'some_func', 'test_function']
>>>
- as 關鍵詞,更名被你引入的module
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_function as ppp
test_function # 但是這里的 __name__ 不會變
>>> dir() # 這里的會變
['__builtins__', '__doc__', '__name__', '__package__', 'ppp']
>>>
>>>
>>> ppp.some_func()
hello
world
100
>>>
- what does python do when you import a module
每次引入一個module,你當前的Python interpreter都會把這個module的代碼逐行執行,所以這里有一個testfunction的輸出,因為源文件里有個 print _name , 但是你在同一個interpreter shell里引入兩次,它就不會執行兩次
- module creates its own namespace
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_function
test_function
>>>
>>>
>>> test_function.some_func()
hello
world
100
>>>
>>> a = 11
>>> test_function.a
100
>>>
>>> a
11
>>>
- 一個有意思的現象,單獨執行那個.py,輸出的name 就是main
這樣也就有了以后的
if name == ‘main‘:
main()
➜ Desktop python test_function.py
__main__
➜ Desktop
所以在別的interpreter shell或者Python文件中引用它時,這個地方name == ‘main‘: 不成立,所以就不會執行if下面的內容,這就提供了一種很好的機制,可以讓我們可以單獨執行源文件里的東西
➜ Desktop cat test_function.py
print __name__
a = 100
def some_func():
print "hello"
print "world"
print a
if __name__ == '__main__':
print "this is excuted by itself"
➜ Desktop
➜ Desktop
➜ Desktop python test_function.py
__main__
this is excuted by itself # 這樣這句話就出來了
➜ Desktop
package/path
- 先說sys.path, 我的理解是,這些path都是可以直接import的,也就是已經install的module和package所在的地方
pprint.pprint(sys.path)是個好辦法,因為直接輸出sys.path看着太混亂了
- 注意下面pprint出來的第一行內容,是個空的string,這就代表了Python會查看本地目錄,也就是一個Python文件自己所在的目錄,也就解釋了之前在同一個目錄Desktop為什么可以直接引用
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import pprint
>>>
>>> pprint.pprint(sys.path)
['',
'/Library/Python/2.7/site-packages/trigger-1.5.2b2-py2.7.egg',
'/Library/Python/2.7/site-packages/redis-2.10.3-py2.7.egg',
'/Library/Python/2.7/site-packages/SimpleParse-2.1.1-py2.7-macosx-10.9-intel.egg',
'/Library/Python/2.7/site-packages/pyparsing-1.5.7-py2.7.egg',
'/Library/Python/2.7/site-packages/pycrypto-2.6.1-py2.7-macosx-10.9-intel.egg',
'/Library/Python/2.7/site-packages/pyasn1-0.1.8-py2.7.egg',
'/Library/Python/2.7/site-packages/IPy-0.83-py2.7.egg',
'/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg',
'/Library/Python/2.7/site-packages/pyPluribus-0.3.0-py2.7.egg',
'/Library/Python/2.7/site-packages',
'/Library/Python/2.7/site-packages/napalm-1.0.0-py2.7.egg',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC',
'/Library/Python/2.7/site-packages']
>>>
- 如何修改sys.path
使用 export命令修改,這個命令也是通用的
為了演示這個過程,我創建了一個文件夾在Desktop, 叫package1
這涉及到了Linux Mac OS X等系統的環境變量的設置,命令是 env ,可以展示當前所有的環境變量,Python的那個值的key是PYTHONPATH
➜ Desktop env | grep PYT #看到目前是沒有設置任何PYTHONPATH變量的
➜ Desktop
下面我去創建一個package1,然后盡管這個folder里什么都還沒有,它還是能被加到PYTHONPATH中
➜ Desktop mkdir package1
➜ Desktop cd package1
➜ package1
➜ package1
➜ package1 pwd
/Users/harry/Desktop/package1
➜ package1 export PYTHONPATH = /Users/harry/Desktop/package1
zsh: bad assignment
➜ package1 export PYTHONPATH=/Users/harry/Desktop/package1
➜ package1 env | grep PYT
PYTHONPATH=/Users/harry/Desktop/package1
➜ package1
進入Python查看一下
➜ package1 python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)
['',
'/Library/Python/2.7/site-packages/trigger-1.5.2b2-py2.7.egg',
'/Library/Python/2.7/site-packages/redis-2.10.3-py2.7.egg',
'/Library/Python/2.7/site-packages/SimpleParse-2.1.1-py2.7-macosx-10.9-intel.egg',
'/Library/Python/2.7/site-packages/pyparsing-1.5.7-py2.7.egg',
'/Library/Python/2.7/site-packages/pycrypto-2.6.1-py2.7-macosx-10.9-intel.egg',
'/Library/Python/2.7/site-packages/pyasn1-0.1.8-py2.7.egg',
'/Library/Python/2.7/site-packages/IPy-0.83-py2.7.egg',
'/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg',
'/Library/Python/2.7/site-packages/pyPluribus-0.3.0-py2.7.egg',
'/Library/Python/2.7/site-packages',
'/Library/Python/2.7/site-packages/napalm-1.0.0-py2.7.egg',
'/Users/harry/Desktop/package1', # <<<<<<<<<<<<<<<<<-------------------------check it out!!!!!!!!
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python27.zip',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload',
'/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC',
'/Library/Python/2.7/site-packages']
>>>
- 往這個package1里加點東西,加init.py才算一個package,這個方法3.3版本前適用,后面再說這個文件干啥用的
➜ package1 pwd
/Users/harry/Desktop/package1
➜ package1 touch __init__.py
➜ package1 ls -al
total 0
drwxr-xr-x 3 harry staff 102 Aug 8 12:14 .
drwxr-xr-x+ 26 harry staff 884 Aug 8 12:01 ..
-rw-r--r-- 1 harry staff 0 Aug 8 12:14 __init__.py
➜ package1
其實這個時候,它才能被稱為是一個package
這個時候我遇到了一個issue,提示ImportError: No module named package1,但是其實pprint都已經顯示了,原因是permission issue,chmod 755 package1/ 就好了
- 往package里價格module,也就是py文件,添加一個p_test.py
➜ Desktop cd package1
➜ package1 vi p_test.py
➜ package1 python p_test.py
hello world, this is excuted by myself
➜ package1
➜ package1
➜ package1 cat p_test.py
def some_func():
print "from some_func"
def another_func():
print "from another func"
if __name__ == '__main__':
print "hello world, this is excuted by myself"
➜ package1
在Python interpreter shell中引用這個p_test.py,引用的格式是 import some_package.some_module
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import package1.p_test
>>>
>>> package1.p_test.some_func()
from some_func
>>>
package1下面還可以創建多個子目錄,依然不用修改sys.path,多個子目錄里就可以放自己想要的module
編輯 init.py ,這里體現了這貨有啥用
先往里隨便加點print
➜ package1 cat __init__.py
print "In __init__.py"
當你再次引用時, 會看到一旦引用,Python會執行init里的print,其實Python會逐條執行這個init,雖然里面可以什么都沒有
現在dir()展開一下namespace會發現沒有p_test存在,如果想用p_test,必須單獨import,init這個文件就是為了解決這個問題的
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import package1
In __init__.py
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'package1']
>>> dir(package1)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']
>>>
發現沒有p_test存在,如果想用p_test,必須單獨import
>>> package1.p_test
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'p_test'
>>>
>>>
>>> import package1.p_test
>>>
>>> package1.p_test
<module 'package1.p_test' from 'package1/p_test.pyc'>
>>>
>>> package1.p_test.some_func()
from some_func
>>>
> - 再次編輯 __init__.py “連接”你想要的file
```sh
➜ package1 vi __init__.py
➜ package1
➜ package1 cat __init__.py
print "In __init__.py"
from . import p_test # from . 的意思是從當前目錄import
這樣ptest就被_init 引用了
再次回到Python,再引用一次package1
namespace都在了
➜ Desktop python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import package1
In __init__.py
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'package1']
>>> dir(package1)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'p_test']
>>> dir(package1.p_test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'another_func', 'some_func']
>>>
p_test這個module也可以用了
>>>
>>> package1.p_test.some_func() # 可以直接這么用
from some_func
>>>
- 關於import現成的module or package
1) 以pprint為例
locate pprint可以找到pprint.py在哪里,一般是在下面這個,看到這個pprint.py就可以認為這是一個 module
/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/pprint.py
打開看一下他其實就是一個py文件,里面是源碼,有作者的info comment等等
2) 以paramiko為例
locate paramiko找到一個叫paramiko的文件夾,在/Library/Python/2.7/site-packages/paramiko 這個路徑
進去看一下會發現,這是一個 package
你可以看到它的 init.py 這個文件,其實你import paramiko的時候,就是它在連接它的各個py文件
➜ paramiko pwd
/Library/Python/2.7/site-packages/paramiko
➜ paramiko ls *.py
__init__.py common.py kex_group14.py resource.py sftp_si.py
_version.py compress.py kex_gss.py rsakey.py ssh_exception.py
_winapi.py config.py message.py server.py ssh_gss.py
agent.py dsskey.py packet.py sftp.py transport.py
auth_handler.py ecdsakey.py pipe.py sftp_attr.py util.py
ber.py file.py pkey.py sftp_client.py win_pageant.py
buffered_pipe.py hostkeys.py primes.py sftp_file.py
channel.py kex_gex.py proxy.py sftp_handle.py
client.py kex_group1.py py3compat.py sftp_server.py
➜ paramiko
一共有42個py文件
➜ paramiko ls *.py | wc -l
42
➜ paramiko
從其他地方看到的關於import的內容
http://stackoverflow.com/questions/6757192/importing-a-function-from-a-class-in-another-file
以上似乎是直接引用,不需要安裝
Head First 上40 - 41頁上講的是如何安裝然后/Library/Python/2.7/site-packages就有了相應的module,在程序里直接 import那個名字即可
卸載
http://stackoverflow.com/questions/1550226/python-setup-py-uninstall
思考:
Head First 上講的是引用一個print多層數組的方法,引用的是一個含有一個方法的.py文件,如果是類的話,用install的話,應該和Head First上的方法是一樣的,如果想直接從文件引用的話,就參考第一個stackoverflow的鏈接,似乎需要在源文件里 always run着一個instance