Python—包介绍
包(Package)
当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹,
.
└── my_proj
├── crm #代码目录
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
└── my_proj #配置文件目录
├── settings.py
├── urls.py
└── wsgi.py
像上面这样,一个文件夹管理多个模块文件,这个文件夹就被称为包
那不同包之间的模块互相导入呢?
crm/views.py内容
def sayhi():
print('hello world!')
通过manage.py调用
from crm import views
views.sayhi()
执行manage.py (注意这里用python2)
Alexs-MacBook-Pro:my_proj alex$ ls
crm manage.py my_proj
Alexs-MacBook-Pro:my_proj alex$ python manage.py
Traceback (most recent call last):
File "manage.py", line 6, in <module>
from crm import views
ImportError: No module named crm
竟然说找不到模块,为什么呢?
包就是文件夹,但该文件夹下必须存在 __init__.py 文件, 该文件的内容可以为空。__int__.py用于标识当前文件夹是一个包。
在crm目录下创建一个空文件__int__.py ,再执行一次就可以了
Alexs-MacBook-Pro:my_proj alex$ touch crm/__init__.py #创建一个空文件
Alexs-MacBook-Pro:my_proj alex$
Alexs-MacBook-Pro:my_proj alex$ ls crm/
__init__.py admin.py models.py views.py
__pycache__ apps.py tests.py views.pyc
Alexs-MacBook-Pro:my_proj alex$ python manage.py
hello world!
注意,在python3里,即使目录下没__int__.py文件也能创建成功,猜应该是解释器优化所致,但创建包还是要记得加上这个文件 吧。
跨模块导入
目录结构如下
.
├── __init__.py
├── crm
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py
├── manage.py
└── proj
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
根据上面的结构,如何实现在crm/views.py
里导入proj/settings.py
模块?
直接导入的话,会报错,说找到不模块
$ python3 views.py
Traceback (most recent call last):
File "views.py", line 2, in <module>
from proj import settings
ModuleNotFoundError: No module named 'proj'
是因为路径找不到,proj/settings.py 相当于是crm/views.py的父亲(crm)的兄弟(proj)的儿子(settings.py),settings.py算是views.py的表弟啦,在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。这可怎么办呢?
答案是添加环境变量,把父亲级的路径添加到sys.path中,就可以了,这样导入 就相当于从父亲级开始找模块了。
crm/views.py中添加环境变量
import sys ,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #__file__的是打印当前被执行的模块.py文件相对路径,注意是相对路径
print(BASE_DIR)
sys.path.append(BASE_DIR)
from proj import settings
def sayhi():
print('hello world!')
print(settings.DATABASES)
输出
$ python3 views.py
/Users/alex/Documents/work/PyProjects/luffy_课件/21天入门/chapter4-常用模块/packages/my_proj
---my proj init--- #proj/__init__.py输出
in proj/settings.py #proj/settings.py输出
{'host': 'localhost'}
*注意;此时在proj/settings.py写上import urls会有问题么?
DATABASES= {
'host':'localhost'
}
import urls #这行刚加的
print('in proj/settings.py')
结果报错了
ModuleNotFoundError: No module named 'urls'
为什么呢? 因为现在的程序入口是views.py , 你在settings.py导入import urls,其实相当于在crm目录找urls.py,而不是proj目录,若想正常导入,要改成如下
DATABASES= {
'host':'localhost'
}
from proj import urls #proj这一层目录已经添加到sys.path里,可以直接找到
print('in proj/settings.py')
绝对导入&相对导入
在linux里可以通过cd ..回到上一层目录 ,cd ../.. 往上回2层,这个..就是指相对路径,在python里,导入也可以通过..
例如:
.
├── __init__.py
├── crm
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py #from ..proj import settings
├── manage.py
└── proj
├── __init__.py
├── settings.py #from .import urls
├── urls.py
└── wsgi.py
views.py里代码
from ..proj import settings
def sayhi():
print('hello world!')
print(settings.DATABASES)
执行结果报错了
Traceback (most recent call last):
File "my_proj/crm/views.py", line 4, in <module>
from ..proj import settings
SystemError: Parent module '' not loaded, cannot perform relative import
或者有人会看到这个错
ValueError: attempted relative import beyond top-level package
其实这两个错误的原因归根结底是一样的:在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。
文件夹被python解释器视作package需要满足两个条件:
- 文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。
- 不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。
所以这个问题的解决办法就是,既然你在views.py里执行了相对导入,那就不要把views.py当作入口程序,可以通过上一级的manage.py调用views.py
.
├── __init__.py
├── crm
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py #from ..proj import settings
├── manage.py #from crm import views
└── proj
├── __init__.py
├── settings.py #from .import urls
├── urls.py
└── wsgi.py
事实证明还是不行,报错
ValueError: attempted relative import beyond top-level package
但把from ..proj import settings
改成from . import models
后却执行成功了,为什么呢?
from .. import models
会报错的原因是,这句代码会把manage.py所在的这一层视作package,但实际上它不是,因为package不能是顶层入口代码,若想不出错,只能把manage.py往上再移一层。
正确的代码目录结构如下
packages/
├── __init__.py
├── manage.py #from my_proj.crm import views
└── my_proj
├── crm
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ ├── views.py #from . import models; from ..proj import settings
└── proj
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
再执行manage.py就不会报错了。
Python—包介绍的更多相关文章
- python包管理-distutils,setuptools,pip,virtualenv等介绍
python包管理-distutils,setuptools,pip,virtualenv等介绍 对于每个编程语言来说打包和发布开发包往往非常重要,而作为一个编程者能够快速容易的获得并应用这些由第三方 ...
- Python包管理工具介绍
常见的包管理工具及关系 setuptools -->distribute easy_install-->pip 1.distribute distribute是对标准库disutils模块 ...
- 【转】linux和windows下安装python集成开发环境及其python包
本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...
- 从零开始学Python第0周:Python基本介绍(部分内容来源于网络)
Python入门介绍 一,Python的基本介绍 (1)概要 Python是一种解释型,面向对象,动态数据类型的高级程序设计语言.常被广泛用于处理系统管理任务和web编程.现如今Python已经成为了 ...
- Python 包管理工具解惑
Python 包管理工具解惑 本文链接:http://zengrong.net/post/2169.htm python packaging 一.困惑 作为一个 Python 初学者,我在包管理上感到 ...
- 【转】Python Twisted介绍
Python Twisted介绍 作者:Jessica McKellar 原文链接 Twisted是用Python实现的基于事件驱动的网络引擎框架.Twisted诞生于2000年初,在当时的网络游戏开 ...
- Python包管理工具和多版本环境管理
1. Python包管理工具 在安装Python包的过程中,经常涉及到distutils.setuptools.distribute.setup.py.easy_install.easy_instal ...
- [Python]Conda 介绍及常用命令
一.介绍 Anaconda 是一个用于科学计算的 Python 发行版,支持 Linux, Mac, Windows, 包含了众多流行的科学计算.数据分析的 Python 包.其使用conda系统进行 ...
- Python包和版本管理的最好工具----pipenv
pipenv 是Kenneth Reitz大神的作品,提供Python的各个版本间的管理,各种包管理.个人觉得是virtualenv pip等工具的合体. pipenv主要有以下特性: (1)以前我们 ...
随机推荐
- [20181219]script使用小技巧.txt
[20181219]script使用小技巧.txt --//前几天在使用strace时遇到问题,它的输出使用标准错误句柄.--//我在想平时使用sqlplus如果输出字段很多,屏幕看起来一片混乱.-- ...
- linux下objdump应用
<a href="http://www.maomao365.com/?p=952" > linux命令objdump的用法 http://www.maomao365. ...
- c/c++ 类模板初探
类模板 1,模板类里的函数都是模板函数 2,模板类里的函数,在类外面实现的时候,要用模板函数(方法:push_back)的方式实现,在类内部实现时,不需要用模板函数(方法:show)方式实现. 3,用 ...
- LeetCode算法题-Add Binary(Java实现)
这是悦乐书的第157次更新,第159篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第16题(顺位题号是67).给定两个二进制字符串,返回它们的总和(也是二进制字符串).输 ...
- spring简述
1. 什么是Spring Spring:SE/EE开发的一站式框架.(有EE开发每一层的解决方案) WEB层:SpringMVC Service层:Spring的Bean管理,Spring的声明式事务 ...
- nginx学习笔记(三)
浏览器缓存
- 在Ubuntu上安装Jenkins
先决条件 安装Java SDK sudo apt-get install openjdk-8-jdk # sudo apt-get install openjdk-7-jdk 早些系统可以安装 第1步 ...
- Linux:Day5 shell编程初步、grep
bash的基本特性(3) 1.提供了编程环境 程序编程风格: 过程式:以指令为中心,数据服务于指令: 对象式:以数据为中心,指令服务于数据: shell程序:提供了编程能力,解释执行:过程式.解释执行 ...
- 三、Oracle 查询+where条件
一.查询1.distinct:查询去除重复的行,是所有的列都重复才满足条件2.列别名:as或者空格 select name as 姓名 from student3.查询字段可以做数学运算,也可以做字符 ...
- 20175330 2018-2019-2 《Java程序设计》第八周学习总结
# **教材学习内容总结### 本周学习<Java程序设计>第十五章:*** 泛型: 泛型(Generics)的主要目的是可以建立具有类型安全的集合框架,如链表.散列映射等数据结构.泛型类 ...