2017年8月

首页2017年8月
28
Aug
0

python3依赖注入方法

1.抽象方法 Bar类里的f2必须要实现 否则编译不通过
import abc

抽象类

class Foo(metaclass=abc.ABCMeta):
    def f1(self):
        print('f1')
    #抽象方法
    @abc.abstractmethod
    def f2(self):
        '''
        打印f2
        '''
class Bar(Foo):
    def f2(self):
        print('f2')
    def f3(self):
        print('f3')
b = Bar()
b.f1()
b.f2()
b.f3()

2.修改__call__方法 可以追加参数,追加函数等等

class MyType(type):
    def __call__(cls,*args,**kwargs):
        obj = cls.__new__(cls,*args,**kwargs)
        print('在这里面..')
        print('==========================')
        print('来咬我呀')
        obj.__init__(*args,**kwargs)
        return obj
class Foo(metaclass=MyType):
    def __init__(self):
        self.name = 'alex'
f = Foo()
print(f.name)

3.一个实例, Mapper可以用作依赖类或实例注册,另一个是实例Bar时,自动关联Foo实例和Head实例

class Mapper:
    #在字典里定义依赖注入关系
    __mapper_relation = {}
    #类直接调用注册关系
    @staticmethod
    def register(cls,value):
        Mapper.__mapper_relation[cls] = value
    @staticmethod
    def exist(cls):
        if cls in Mapper.__mapper_relation:
            return True
        return False
    @staticmethod
    def get_value(cls):
        return Mapper.__mapper_relation[cls]
class MyType(type):
    def __call__(cls,*args,**kwargs):
        obj = cls.__new__(cls,*args,**kwargs)
        arg_list = list(args)
        if Mapper.exist(cls):
            value = Mapper.get_value(cls)
            arg_list.append(value)
        obj.__init__(*arg_list,**kwargs)
        return obj
class Head:
    def __init__(self):
        self.name = 'alex'
class Foo(metaclass=MyType):
    def __init__(self,h):
        self.h = h
    def f1(self):
        print(self.h)
class Bar(metaclass=MyType):
    def __init__(self,f):
        self.f = f
    def f2(self):
        print(self.f)
Mapper.register(Foo,Head())
Mapper.register(Bar,Foo())
b = Bar()
print(b.f)

ps.继承自object和继承type方法一样

24
Aug
0

自循环程序的关闭方法

利用获取系统关闭信号的原理来关闭程序
主要用到linux信号和管道两种技术
此方法在win下 SIGHUP信号是没有的,其它和linux下完全相同

from multiprocessing import Pipe
import signal

recv,send = Pipe(False)
def stop(sig,former):
    global send
    print('send terminat')
    print(sig,former)
    send.send('ok')


signal.signal(signal.SIGINT, stop)
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGHUP, stop)

if __name__ == '__main__':
    ServiceManager.init()
    while True:
        value = recv.recv()
        if value == 'ok':
            break
24
Aug
0

动态移除装饰器的执行方法

要求1.python3

要求2.必须wraps包装的装饰器

from functools import wraps

def outfun(fun):
    @wraps(fun)
    def innerfun(x,name):
        print('innerfun')
        fun(x,name)
    return innerfun

class ac(object):
    @outfun
    def foo(self,name):
        print('foo',name)

a = ac()
a.foo('lisi')
a.foo('zhangsan')
a.foo.__wrapped__(a,'kkkk')

结果:
innerfun
foo lisi
innerfun
foo zhangsan
foo kkkk

23
Aug
0

python3新增参数类型 命令关键字 拆分参数

原有参数类型有
必选参数、默认参数、可变参数、关键字参数

python3新增命名关键字参数

传入的参数名称必须与函数定义的参数命名一致,否则就会报错,在定义命名关键字参数时,

命名关键字的参数前面要加一个*,符号分隔

def create_user(*, name, age):
    print(name, age)

访问时必须

create_user(name='arthur', age=18)

如果不写参数名,就报错,可以不按顺序

函数内参数名前加* 代表拆分值

class ck(object):
    _boy = 'boy'
    _girl = 'girl'

def createss(name):
    print(name._girl)
    print(*name._girl)
    c = [*name._boy,'abd','ffff']
    print(c)
    d = '  '.join(c)
    print(d)

cc = ck()
createss(cc)

结果为:
girl
g i r l
['b', 'o', 'y', 'abd', 'ffff']
b o y abd ffff

无法探察类型是什么 此方法会报错
type(*name._girl)

但单个拆分值为str
type(*name._girl[0])

so无法判断类型 留着以后再折腾

22
Aug
0

将包发布到pypi

最近需要把基础库移出来进行单独更新,更新最方便的方式无疑是放到pypi喽

网上教程很多, 算是很容易的了 ,我这个也只是跟着来了一遍而已

注意点如下:

1.项目目录如下:

20170822155528.jpg

HttpTester是源码目录,这种目录格式会造成引用包时需要用HttpTester.HttpTester.HttpMutiTester
如果是简单库的话 最好是直接在源码目录里创建我们的库 减少引用层数

2.上传前先注册包这步,现在不需要了

3.py_modules = ['SDLCSService'],是当前目录的文件 引用时是单层 可以当作主入口

4.packages=find_packages(), 可以用find去自动找子包,要不然不会打包

5.MANIFEST.in 文件可以打包其它的配置文件,图片等等

 内容如:
include Conf/*.conf
recursive-include examples *.txt *.py
prune examples/sample?/build

recursive-include 递归目录下的
prune 移除
include 包含

//上面完成,静态文件虽然会打包,但是不会安装时目录 比如:.conf文件 html文件
//下面两行加入会放到安装目录
packages=find_packages(exclude=["."]),
include_package_data=True,

这下面是网上的教程:

1、整理代码的目录结构,方便打包和python的import,为了方便引用,需要将代码模块变成一个包,所以需要将功能代码用目录来整合方便引用,并且需要创建__init__文件,__init__中可以没有内容,也可以在__init__文件中进行import(from .extractor import Document)操作,以减少整体模块引用时import的层数,避免错误。
├── ./tidypage
│ ├── ./tidypage/cleaners.py
│ ├── ./tidypage/extractor.py
│ ├── ./tidypage/__init__.py
│ └── ./tidypage/titles.py

2、功能模块的目录整理好后,就可以开始整理和添加发布到pypi上所使用的文件了
tidy_page
├── LICENSE
├── README.rst
├── requirements.txt
├── setup.py
├──tidypage
│ ├──cleaners.py
│ ├──extractor.py
│ ├──__init__.py
│ └──titles.py

就是将原来的目录深移一层,文件夹名称可以根据自己意愿。然后在到第一层的目录下创建些特殊文件,具体你可以看看下面这个文件结构你就明白了

LICENSE文件是授权文件,比如:MIT license, APACHE license
README.rst 文件想必大家都不陌生,其实就是项目介绍和使用说明
setup文件才是重点,是python模块安装所需要的文件,它的格式如下:

!/usr/bin/env python

from future import print_function
from setuptools import setup, find_packages
import sys

setup(

name="tidy-page",
version="0.1.1",
author="Desion Wang",
author_email="wdxin1322@qq.com",
description="html text parser,get the content form html page",
long_description=open("README.rst").read(),
license="MIT",
url="https://github.com/desion/tidy_page",
packages=['tidypage'],
py_modules = ['SDLCSService'],
install_requires=[
    "beautifulsoup4",
    lxml_requirement
    ],
classifiers=[
    "Environment :: Web Environment",
    "Intended Audience :: Developers",
    "Operating System :: OS Independent",
    "Topic :: Text Processing :: Indexing",
    "Topic :: Utilities",
    "Topic :: Internet",
    "Topic :: Software Development :: Libraries :: Python Modules",
    "Programming Language :: Python",
    "Programming Language :: Python :: 2",
    "Programming Language :: Python :: 2.6",
    "Programming Language :: Python :: 2.7",
],

)

NAME 名字,一般放你包的名字即可

PACKAGES 包含的包,可以多个,这是一个列表

DESCRIPTION 关于这个包的描述

LONG_DESCRIPTION 参见read方法说明

KEYWORDS 关于当前包的一些关键字,方便PyPI进行分类。

AUTHOR 谁是这个包的作者,写谁的名字吧

AUTHOR_EMAIL 作者的邮件地址

URL 你这个包的项目地址,如果有,给一个吧,没有你直接填写在PyPI你这个包的地址也是可以的

VERSION 当前包的版本,这个按你自己需要的版本控制方式来

LICENSE 授权方式

INSTALL_REQUIRES 模块所依赖的python模块

文中的classifiers的内容并不是随便填写的,你需要参照本文参考文档中的PyPI Classifiers来写

3、开始使用Distutils进行打包

为了保证效果,在打包之前我们可以验证setup.py的正确性,执行下面的代码
python setup.py check

输出一般是running check

如果有错误或者警告,就会在此之后显示

没有任何显示表示Distutils认可你这个setup.py文件。

如果没有问题,那么就可以正式打包,执行下面的代码:

python setup.py sdist

执行完成后,会在顶层目录下生成dist目录和egg目录

tidy_page
├── tidy_page/dist
│ ├── tidy_page/dist/tidy-page-0.1.0.tar.gz
│ └── tidy_page/dist/tidy-page-0.1.1.tar.gz
├── tidy_page/LICENSE
├── tidy_page/README.rst
├── tidy_page/setup.py
├── tidy_page/tidypage
│ ├── tidy_page/tidypage/cleaners.py
│ ├── tidy_page/tidypage/extractor.py
│ ├── tidy_page/tidypage/__init__.py
│ └── tidy_page/tidypage/titles.py
├── tidy_page/tidy_page.egg-info
│ ├── tidy_page/tidy_page.egg-info/dependency_links.txt
│ ├── tidy_page/tidy_page.egg-info/PKG-INFO
│ ├── tidy_page/tidy_page.egg-info/requires.txt
│ ├── tidy_page/tidy_page.egg-info/SOURCES.txt
│ └── tidy_page/tidy_page.egg-info/top_level.txt

4、打包完成后就可以准备将打包好的模块上传到pypi了,首先你需要在pypi上进行注册 goto PyPI Live

    注册完成后,你需要在本地创建好pypi的配置文件,不然有可能会出现使用http无法上传到pypi的问题
     Create a .pypirc configuration file,在用户的home目录下创建.pypirc文件,文件的内容如下

[distutils]
index-servers = pypi

[pypi]
repository=https://pypi.python.org/pypi
username=your_username
password=your_password

chmod 600 ~/.pypirc
生成上面这个文件可以用python setup.py register
在pypi上注册模块
python setup.py register -r pypi
上传
python setup.py sdist upload -r pypi

windows下使用
python setup.py register注册名称就会报错
AssertionError: unsupported schema
只能用 twine

pip install twine
它不能自动上传最新那个  只能删掉旧的
twine upload dist/*