Python问题记录-1

2021-03-10  本文已影响0人  王国的荣耀

python 项目生成requirements.txt等文件

pip install pipreqs
# 项目目录执行
pipreqs ./

python call 方法

Call self as a function
主要实现的是将类的对象当作函数直接调用

# 
class type(object):
      def __call__(self, *args, **kwargs): # real signature unknown
              """ Call self as a function. """
              pass

call示例

def __call__(self, environ, start_response):
        self.proxied = False
        script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
        if script_name:
            self.proxied = True
            environ['SCRIPT_NAME'] = script_name
            path_info = environ.get('PATH_INFO', '')
            if path_info and path_info.startswith(script_name):
                environ['PATH_INFO'] = path_info[len(script_name):]

        scheme = environ.get('HTTP_X_SCHEME', '')
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        servr = environ.get('HTTP_X_FORWARDED_HOST', '')
        if servr:
            environ['HTTP_HOST'] = servr
            self.proxied = True
        return self.app(environ, start_response)

Django、Tornado、Flask比较

使用flask好久,感觉flask还是好用些。

Django是Python 中最全能的 web 开发框架,走大而全的方向。它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。不过Django提供的方便,也意味着Django内置的ORM跟框架内的其他模块耦合程度高,深度绑定了该框架,应用程序必须使用Django内置的ORM,否则就不能享受到框架内提供的种种基于其ORM的优秀特性。

Tornado全称Tornado Web Server,是一个用Python语言写成的Web服务器兼Web应用框架。Tornado走的是少而精的方向,注重的是性能优越,它最出名的是异步非阻塞的服务器方式。(Tornado框架和服务器一起组成一个WSGI的全栈替代品。单独在WSGI容器中使用tornado web框架或者tornaod http服务器,有一定的局限性,为了最大化的利用tornado的性能,推荐同时使用tornaod的web框架和HTTP服务器。)

Flask是一个使用 Python 编写的轻量级 Web 应用框架,也被称为 “microframework”,语法简单,部署很方便,整个框架自带了路径映射、模板引擎(Jinja2)、简单的数据库访问等web框架组件,支持WSGI协议(采用 Werkzeug)。Flask使用 BSD 授权。 Flask使用简单的核心,用 extension 增加其他功能,虽然没有默认使用的数据库、窗体验证工具,然而Flask保留了扩增的弹性,可以用Flask-extension加入ORM、窗体验证工具、文件上传、各种开放式身份验证技术这些功能。

从性能上看Tornado 比Django、Flask等主流 Web 服务器框架相比有着明显的区别:它是非阻塞式服务器,速度相当快。然而 Tornado 相比 Django 和Flask属于较为原始的框架,插件少,许多内容需要自己去处理。而Flask插件多,文档非常专业,有专门的公司团队维护,对于快速开发很有效率。由于WSGI协议的存在,可以结合 Tornado 的服务器异步特性、并发处理能力和Flask的文档和扩展能力为一体。虽然像Django,Flask框架都有自己实现的简单的WSGI服务器,但一般用于服务器调试,生产环境下建议用其他WSGI服务器,比如Nginx+uwsgi+Django方式。

参考

python-tornado简单使用
Python的web架构之Tornado+Flask

python 装饰器

装饰器能够在那个函数执行前或者执行后分别运行一些代码,使得可以再装饰器里面访问并修改原函数的参数以及返回值,以实现约束定义、调试程序、注册函数等目标。装饰器一般返回一个包装器(wrapper),而functools.wraps就是装饰包装器的装饰器。

自己创建一个装饰器

def a_new_decorator(a_func):
    def wrapTheFunction():
        print("I am doing some boring work before executing a_func()")
        a_func()
        print("I am doing some boring work after executing a_func()")
        return wrapTheFunction

def a_function_requiring_decoration():
    print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
#        I am the function which needs some decoration to remove my foul smell
#        I am doing some boring work after executing a_func()
from functools import wraps
def a_new_decorator(a_func):
    @wraps(a_func)
    def wrapTheFunction():
        print("I am doing some boring work before executing a_func()")
        a_func()
        print("I am doing some boring work after executing a_func()")
        return wrapTheFunction

@a_new_decorator
def a_function_requiring_decoration():
    """Hey you! Decorate me!"""
    print("I am the function which needs some decoration to "
          "remove my foul smell")

a_function_requiring_decoration()

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
print(a_function_requiring_decoration.__name__)

输出结果为

I am doing some boring work before executing a_func()
I am the function which needs some decoration to remove my foul smell
I am doing some boring work after executing a_func()

a_function_requiring_decoration

python 修饰符@

修饰符@的作用是为现有函数增加额外的功能,常用于插入日志、性能测试、事务处理等等。
创建函数修饰符的规则:
(1)修饰符是一个函数
(2)修饰符取被修饰函数为参数
(3)修饰符返回一个新函数
(4)修饰符维护被维护函数的签名

修饰符@是一个函数

def log(func):
    def wrapper():
        print('log开始 ...')
        func()
        print('log结束 ...')
    return wrapper

@log
def run_func():
    print('run_func ..')

run_func()
#log开始 ...
#run_func ..
#log结束 ...

修饰符@维护被维护函数的签名

使用functools模块提供的修改函数属性的方法wraps

from functools import wraps

def log(func):
    @wraps(func)
    def wrapper():
        print('log开始 ...')
        func()
        print('log结束 ...')
    return wrapper
    
@log
def test1():
    print('test1 ..')

def test2():
    print('test2 ..')

print(test1.__name__)
print(test2.__name__)

#test1
#test2

被修饰函数带参数

from functools import wraps

def log(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        print('log开始 ...',func.__name__)
        ret = func(*args,**kwargs)
        print('log结束 ...')
        return ret
    return wrapper
    
@log
def test1(s):
    print('test1 ..', s)
    return s

@log
def test2(s1, s2):
    print('test2 ..', s1, s2)
    return s1 + s2


test1('a')
test2('a','bc')

参考

python 函数修饰符@

python 打开文件

f = file(name[, mode[, buffering]])
入口参数: name 文件名
mode 选项,字符串
buffering 是否缓冲 (0=不缓冲,1=缓冲, >1的int数=缓冲区大小)
返回值 : 文件对象
mode 选项:
"r" 以读方式打开,只能读文件 , 如果文件不存在,会发生异常
"w" 以写方式打开,只能写文件, 如果文件不存在,创建该文件
如果文件已存在,先清空,再打开文件
"rb" 以二进制读方式打开,只能读文件 , 如果文件不存在,会发生异常
"wb" 以二进制写方式打开,只能写文件, 如果文件不存在,创建该文件
如果文件已存在,先清空,再打开文件
"rt" 以文本读方式打开,只能读文件 , 如果文件不存在,会发生异常
"wt" 以文本写方式打开,只能写文件, 如果文件不存在,创建该文件
如果文件已存在,先清空,再打开文件
"rb+" 以二进制读方式打开,可以读、写文件 , 如果文件不存在,会发生异常
"wb+" 以二进制写方式打开,可以读、写文件, 如果文件不存在,创建该文件
如果文件已存在,先清空,再打开文件

python3.8使用flask_wtf时产生的cannot import name 'url_encode'问题

werkzeug 版本过高,导致问题出现;安装werkzeug的低版本即可解决问题
pip install werkzeug==0.16.0

flask 渲染html

from flask import render_template

@app.route('/user/')
def user():
    return render_template('user.html')
if __name__ == '__main__':
    app.run(debug=True)


# user.html 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>这是用户中心</title>
    <h1>这是用户中心! </h1>
</head>
<body>

</body>
</html>

python 3.7 async=True, get_object=False, no_input=False):

pip install pyspider
pyspider
➜  Containers Pyspider
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/bin/Pyspider", line 5, in <module>
    from pyspider.run import main
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 231
    async=True, get_object=False, no_input=False):
    ^

原因是python3.7中async已经变成了关键字。因此出现这个错误。
修改方式是手动替换一下

下面位置的async改为mark_async
/usr/local/lib/python3.7/site-packages/pyspider/run.py 的231行、245行(两个)、365行
/usr/local/lib/python3.7/site-packages/pyspider/webui/app.py 的95行
/usr/local/lib/python3.7/site-packages/pyspider/fetcher/tornado_fetcher.py 的81行、89行(两个)、95行、117行

 ~ pyspider
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/bin/pyspider", line 8, in <module>
    sys.exit(main())
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 754, in main
    cli()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 1236, in invoke
    return Command.invoke(self, ctx)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 165, in cli
    ctx.invoke(all)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/run.py", line 467, in all
    threads.append(run_in(ctx.invoke, phantomjs, **phantomjs_config))
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyspider/libs/utils.py", line 68, in run_in_subprocess
    thread.start()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/process.py", line 121, in start
    self._popen = self._Popen(self)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/context.py", line 284, in _Popen
    return Popen(process_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 32, in __init__
    super().__init__(process_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_fork.py", line 19, in __init__
    self._launch(process_obj)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/popen_spawn_posix.py", line 47, in _launch
    reduction.dump(process_obj, fp)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/multiprocessing/reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function cli at 0x7fe59a5735e0>: it's not the same object as pyspider.run.cli

解决方法:使用pipenv

参考

https://www.cnblogs.com/jiguanghover/p/11364513.html

python 多线程实现同步的四种方式

https://www.cnblogs.com/zhumengke/articles/10825242.html

Python raise

http://c.biancheng.net/view/2360.html

Python functools.partial

partial adj. 局部的;偏爱的;不公平的
Python 提供了一个 functools 的模块,该模块为高阶函数提供支持,partial 就是其中的一个函数

def  add(x, y):
    return x + y

 add(3, y=2)
 add(4, y=2)
 add(5, y=2)


def plus(x, y=2):
    return add(x, y)

plus(3)
plus(4)
plus(5)


from functools import partial
plus = partial(add, y=2)

partial 接收函数 add 作为参数,固定 add 的参数 y=2,并返回一个新的函数给 plus。简单而言,partial 函数的功能就是:把一个函数的某些参数给固定住,返回一个新的函数。

参考

python标准库--functools.partial

端口转发

server{
 listen 80;
 server_name  tomcat.shaochenfeng.com;
 index  index.php index.html index.htm;

 location / {
   proxy_pass  http://127.0.0.1:8080; # 转发规则
   proxy_set_header Host $proxy_host; # 修改转发请求头,让8080端口的应用可以受到真实的请求
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 }
}
上一篇下一篇

猜你喜欢

热点阅读