我是一名 Java 开发人员并开始学习 Python 语言,最近我遇到了使用异步 greenlets 的 Python Gevent 库。有人可以解释我,如何使用 Gevent 在 Python 中同步、死锁、活锁工作/避免。
我正在阅读http://sdiehl.github.io/gevent-tutorial/。在页面底部的示例中,我看到:
import gevent.monkey
gevent.monkey.patch_socket()
Run Code Online (Sandbox Code Playgroud)
我读过什么是猴子补丁?,它给出了猴子补丁的一般讨论,但我不明白为什么 gevent 引用了猴子补丁。
从 gevent 文档:
greenlet 都运行在同一个操作系统线程中,并被协同调度。
那么是否还需要使用gevent lock原语或者gevent.Queue来避免单个线程中多个greenlet之间的竞争条件?一个演示这种竞争条件的例子将不胜感激。根据我自己的理解,这些同步原语似乎只是在 greentlets 之间切换执行流程的一种方式。
这是有问题的代码(一个非常简单的爬虫),该文件是一个 url 列表,通常大于 1000。
import sys, gevent
from gevent import monkey
from gevent.pool import Pool
import httplib, socket
from urlparse import urlparse
from time import time
pool = Pool(100)
monkey.patch_all(thread=False)
count = 0
size = 0
failures = 0
global_timeout = 5
socket.setdefaulttimeout(global_timeout)
def process(ourl, mode = 'GET'):
global size, failures, global_timeout, count
try:
url = urlparse(ourl)
start = time()
conn = httplib.HTTPConnection(url.netloc, timeout = global_timeout)
conn.request(mode, ourl)
res = conn.getresponse()
req = res.read()
end = time()
bytes = len(req) …Run Code Online (Sandbox Code Playgroud) 我有两个函数从两个不同的连接接收数据,我应该在从其中之一获得结果后关闭这两个连接。
def first():
gevent.sleep(randint(1, 100)) # i don't know how much time it will work
return 'foo'
def second():
gevent.sleep(randint(1, 100)) # i don't know how much time it will work
return 'bar'
Run Code Online (Sandbox Code Playgroud)
然后我生成每个函数:
lst = [gevent.spawn(first), gevent.spawn(second)]
Run Code Online (Sandbox Code Playgroud)
gevent.joinall阻塞当前的 greenlet,直到两个 greenlet 都lst准备好。
gevent.joinall(lst) # wait much time
print lst[0].get(block=False) # -> 'foo'
print lst[1].get(block=False) # -> 'bar'
Run Code Online (Sandbox Code Playgroud)
我想等到第一个或第二个 greenlet 准备好:
i_want_such_function(lst) # returns after few seconds
print lst[0].get(block=False) # -> 'foo' because this greenlet is ready
print …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用set():
adjacent = filter(lambda p: p[0] in xp and p[1] in yp, p_data)
adjacent = set(adjacent)
Run Code Online (Sandbox Code Playgroud)
但是,我收到此错误:
Traceback (most recent call last):
File "/home/anarchist/Desktop/python27/lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "/home/anarchist/Desktop/BSpaces/BrochureSpaces/imageProcessing/__init__.py", line 60, in findViewPorts
adjacent = set(adjacent)
UnboundLocalError: local variable 'set' referenced before assignment
<Greenlet at 0x15879b0: <bound method rawImage.findViewPorts of <BrochureSpaces.imageProcessing.rawImage instance at 0x7f7177356830>>(image_file='image_t.png')> failed with UnboundLocalError
Run Code Online (Sandbox Code Playgroud)
码:
class rawImage:
def __init__(self, **kwargs):
logging.root.setLevel(logging.DEBUG)
self.p_data = [] # Positions of all non opaque …Run Code Online (Sandbox Code Playgroud) 当我使用标准logging包从greenlet中打印出日志语句时,我得到的文本如下所示:
2014-02-06 22:38:43,428 [INFO] (11396-Dummy-2) event_listener: About to block
Run Code Online (Sandbox Code Playgroud)
我指的是这个11396-Dummy-2部分.我希望它能说出像'Main'或'Listener 1'这样的东西.这可能吗?从当前的文档中我没有看到任何API这样做.
我在使用 gevent 运行 Celery 时遇到性能负载问题,所有内容都在我的 VPS 上的同一核心上运行。
这是 4 个 Celery 实例的屏幕截图,每个实例有 20 个 gevent 并发
如何解决这个问题?我究竟做错了什么 ?
这是我的第一个任务:
def update_sender():
items = models.Item.objects.filter(active=True).all()
count = items.count()
items = [i.id for i in items]
step = count / settings.WORKERS
for job in list(chunks(items, step)):
update_item.apply_async(args=[job])
Run Code Online (Sandbox Code Playgroud)
调用以下子任务:
def update_item(items):
for item in items:
try:
i = models.Item.objects.get(id=item)
url = "someurl"
rep = requests.get(url)
jrep = rep.json()
tracker = ItemTracker(i, jrep)
if tracker.skip():
continue
if tracker.method1():
if not tracker.method2():
tracker.method3()
tracker.save()
Run Code Online (Sandbox Code Playgroud)
这都是关于同时执行大量 …
有什么问题?
我在PyCharm(版本2016.1.4)中使用远程解释器(而不是Debug Server!)进行了远程调试,如下所述:jetbrains网站。
当我在“调试”模式下运行时,程序会在断点处按其应有的方式停止。但是,在“变量”窗口中不会显示变量。相反,我得到以下错误:
无法显示框架变量
我想这是同样的问题:链接
我尝试了什么?
我发现此链接提供了可能的解决方案,但对我而言不起作用。基于此解决方案,我对helpers/pydev/_pydevd_bundle/pydevd_constants.py文件进行了如下修改:
从:
try:
SUPPORT_GEVENT = os.getenv('GEVENT_SUPPORT', 'False') == 'True'
except:
# Jython 2.1 doesn't accept that construct
SUPPORT_GEVENT = False
# At the moment gevent supports Python >= 2.6 and Python >= 3.3
USE_LIB_COPY = SUPPORT_GEVENT and \
((not IS_PY3K and sys.version_info[1] >= 6) or
(IS_PY3K and sys.version_info[1] >= 3))
Run Code Online (Sandbox Code Playgroud)
至:
try:
SUPPORT_GEVENT = os.getenv('GEVENT_SUPPORT', 'False') == 'True'
try:
import gevent
SUPPORT_GEVENT = True
except:
SUPPORT_GEVENT …Run Code Online (Sandbox Code Playgroud) 我正在尝试制作一个使用 WebSockets 的 Flask 应用程序。Flask-sockets 中的示例有效,但我如何从常规视图发送消息?
.emit()与 Flask-SocketIO 如何使用和方法类似.send()。
在下面的示例中(来自 Flask-Sockets 示例),我希望能够从 -view 广播消息hello。
from flask import Flask
from flask_sockets import Sockets
app = Flask(__name__)
sockets = Sockets(app)
@sockets.route('/echo')
def echo_socket(ws):
while not ws.closed:
message = ws.receive()
ws.send(message)
@app.route('/')
def hello():
# How can I send a WebSocket message from here?
return 'Hello World!'
if __name__ == "__main__":
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
server.serve_forever()
Run Code Online (Sandbox Code Playgroud) 一切都很好?我使用docker build时遇到问题.此应用程序已安装在其他2台计算机上,但每次发生此错误时.有谁知道我应该做些什么来解决它.我有一个Windows 10,我正在使用Docker Toolbox.
我在网站上尝试了这个答案,没有成功:
我按照docker自己的网站上的对接教程:
https://docs.docker.com/compose/django/#define-the-project-components
Dockerfile
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
RUN pip3 install virtualenv
RUN virtualenv /code
ADD requirements.txt /code/
RUN python -m pip install -r requirements.txt --no-cache-dir
ADD . /code/
Run Code Online (Sandbox Code Playgroud)
错误日志:
PS C:\Users\ThinkPad\Documents\ChatBot> docker build -t backend .
Sending build context to Docker daemon 209.5MB
Step 1/9 : FROM python:3
---> ce54ff8f2af6
Step 2/9 : ENV PYTHONUNBUFFERED 1
---> Using cache
---> 5cefadc9e069
Step 3/9 : RUN mkdir /code
---> …Run Code Online (Sandbox Code Playgroud) 我有以下Python代码:
>>> import gevent
>>> from gevent import monkey; monkey.patch_all()
>>>
>>> def fooFn(k):
... return 'gevent_'+k
...
>>> threads = []
>>> threads.append(gevent.spawn(fooFn,'0'))
>>> threads.append(gevent.spawn(fooFn,'1'))
>>>
>>> gevent.joinall([threads[1]])
>>>
>>> print threads[1].value
gevent_1
>>> print threads[0].value
gevent_0
>>>
Run Code Online (Sandbox Code Playgroud)
如上所示,threads[0].value从中获得了适当的值fooFn。这意味着threads[0]greenlet已执行。
当我仅将threads[1]greenlet 传递给时,为什么会发生这种情况gevent.joinall?
我如何确保仅执行实际传递给的那些greenlet gevent.joinall?
我在基于gevent的框架上将pymongo驱动程序与mongodb一起使用。我不了解工作池连接。我在每个请求上创建一个新的连接实例:
connection = MongoClient(host='localhost', port=27017, use_greenlets=True)
Run Code Online (Sandbox Code Playgroud)
实际是从一个池中取得连接?
现在,如果我进行连接:
connection = MongoClient(host='localhost', port=27017)
Run Code Online (Sandbox Code Playgroud)
这是来自同一池的连接吗?如果给MongoClient调用不同的参数会怎样?