我已经用Python编程了几年,并且一直使用CPython而不考虑它.我读过的书籍和文档也总是指CPython.
何时使用替代分发(PyPy,Stackless等)是有意义的?
谢谢!
我正在为contstant(每个30-120秒)编写一个脚本来获取大量URL(Icecast/Shoutcast服务器状态页面)的信息,大约500个网址.它工作正常,但python进程驻留大小不断增长.我确信它会无限增长,因为我让它运行了几个小时,从最初的30Mb开始需要1.2Gb RES.
我简化了脚本以便于理解以下内容:
from twisted.internet import reactor
from twisted.web.client import getPage
from twisted.enterprise import adbapi
def ok(res, url):
print "OK: " + str(url)
reactor.callLater(30, load, url)
def error(res, url):
print "FAIL: " + str(url)
reactor.callLater(30, load, url)
def db_ok(res):
for item in res:
if item[1]:
print "ADDED: " + str(item[1])
reactor.callLater(30, load, item[1])
def db_error(res):
print "Database error: " + str(res)
reactor.stop()
def load(url):
d = getPage(url,
headers={"Accept": "text/html"},
timeout=30)
d.addCallback(ok, url)
d.addErrback(error, url)
dbpool = adbapi.ConnectionPool("MySQLdb", "host", "user", "passwd", …Run Code Online (Sandbox Code Playgroud) 我有一个嵌入式Python程序,它在C中的一个线程中运行.
当Python解释器切换线程上下文(让控制到另一个线程)时,我希望得到通知,以便我可以执行某些必要的操作.
这似乎Py_AddPendingCall正是我正在寻找的.但是,API文档在这个函数上非常简短,我对应该如何Py_AddPendingCall使用感到困惑.通过阅读文档,我的理解是:
Py_AddPendingCall并分配处理函数.我用Google搜索了一些显示如何使用的代码Py_AddPendingCall,但我找不到任何东西.我自己尝试使用它根本行不通.永远不会调用处理程序.
我的工作线程代码:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
const char* PYTHON_CODE =
"while True:\n"
" for i in range(0,10): print(i)\n"
"\n";
int handler(void* arg)
{
printf("Pending Call invoked!\n");
abort();
}
void* worker_thread(void*)
{
PyGILState_STATE state = PyGILState_Ensure();
int res = Py_AddPendingCall(&func, nullptr);
cout << "Result: " << res << endl;
PyRun_SimpleString(CODE);
PyGILState_Release(state);
return 0;
}
int main()
{
Py_Initialize();
PyEval_InitThreads();
PyEval_ReleaseLock();
pthread_t threads[4];
for …Run Code Online (Sandbox Code Playgroud) 据我所知,Global Interpreter Lock只允许一个线程访问解释器并执行字节码.如果是这种情况,那么在任何给定时间,只有一个线程将使用解释器及其内存.
有了这个,我认为排除有种族案例的可能性是公平的,因为没有两个线程可以同时访问解释器的内存,但我仍然看到关于确保数据结构是"线程安全"的警告.它有可能覆盖python解释器的所有实现(如cython),它可以关闭GIL并允许真正的多线程.
我理解线程安全在没有启用GIL的解释器环境中的重要性.但是,对于CPython,为什么在编写多线程python代码时会鼓励线程安全?在CPython环境中可能发生的更糟糕的是什么?
异步文档阅读:
大多数异步对象不是线程安全的。您仅应担心在事件循环之外访问对象。
有人可以解释一下还是举一个例子说明如何滥用asyncio导致线程之间共享的对象不同步写入?我认为GIL意味着一次只能有一个线程可以运行解释器,因此解释器中发生的事件(例如读取和写入Python对象)在线程之间是微不足道的同步。
上面引用的第二句话听起来像个线索,但我不确定该怎么做。
我猜想线程可能总是会因释放GIL并决定以任何方式写入Python对象而造成严重破坏,但这不是特定于asyncio的,因此我认为文档不是这里所指的。
这是否可能是异步PEP保留某些异步对象不是线程安全的选项的问题,即使目前在CPython中的实现恰好是线程安全的呢?
python cpython python-multithreading thread-synchronization python-asyncio
简单的2 ++ 2如何在Python语言的幕后工作?
如果我们在Python解释器中输入:
>>> 2+++--2
4
>>> 2+++*2
File "<stdin>", line 1
2++*2
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
在这里看一下语法错误,我注意到它是Python设计者设计/实现Python的方式.
据说Python是开源代码,所以我开始更多地探索它.我已经阅读了很多关于Python实现的文章,使用cpython.
所以这里Python编译器很容易识别这些++*%-是运算符.因为它是用C语言编写的.C使用一些直接汇编代码编译器,然后转换为机器代码.
问题1: Python编译器如何识别运算符?(关于词法和解析功能)
问题2:我如何修改Python解释器的这种简单行为,它可以抛出语法错误,使多个运算符与多次运算符相同
>>> 2**2
4
>>> 2***2
File "<stdin>", line 1
2***2
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
我已经阅读了cpython的这些文件:compile.c parser.c,readline.c
但是我没有遇到任何关于语法错误的异常处理机制的文件.
更新:
我仍在搜索并等待问题2的任何答案
从Python 3.7的新增功能中,
我们可以看到有新的math.remainder。它说
返回关于y的x的IEEE 754样式余数。对于有限x和有限非零y,这是差异
x - n*y,其中n是最接近商的精确值的整数x / y。如果x / y恰好位于两个连续整数之间,则将最接近的偶数整数用于n。因此,其余部分r = remainder(x, y)始终令人满意abs(r) <= 0.5 * abs(y)。特殊情况遵循IEEE 754:尤其
remainder(x, math.inf)是对于任何有限X X和remainder(x, 0)和remainder(math.inf, x)提高ValueError任何非NaN的X。如果余数运算的结果为零,则该零将具有与x相同的符号。在使用IEEE 754二进制浮点的平台上,此操作的结果始终可以精确表示:不引入舍入错误。
但我们也要记住,有一个%符号是
其余
x / y
我们还看到操作员需要注意:
不适用于复数。相反,
abs()如果合适,使用转换为浮点数。
我甚至没有尝试过运行python 3.7。
但是我尝试过
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin …Run Code Online (Sandbox Code Playgroud) 我将Python嵌入到应用程序中。用户通过以下方式安装软件包或模块时
{...}\myapp\python\python.exe setup.py install
Run Code Online (Sandbox Code Playgroud)
软件包将安装在
{...}\myapp\python\lib\site-packages
Run Code Online (Sandbox Code Playgroud)
Is there any chance to use another directory instead by default?
我试图找出是否有可能解决堆栈帧中的变量(如返回inspect.currentframe()).
换句话说,我正在寻找一个功能
def resolve_variable(variable_name, frame_object):
return value_of_that_variable_in_that_stackframe
Run Code Online (Sandbox Code Playgroud)
例如,请考虑以下代码:
global_var = 'global'
def foo():
closure_var = 'closure'
def bar(param):
local_var = 'local'
frame = inspect.currentframe()
assert resolve_variable('local_var', frame) == local_var
assert resolve_variable('param', frame) == param
assert resolve_variable('closure_var', frame) == closure_var
assert resolve_variable('global_var', frame) == global_var
bar('parameter')
foo()
Run Code Online (Sandbox Code Playgroud)
局部和全局变量平凡通过抬头f_locals和f_globals框架对象的属性:
def resolve_variable(variable_name, frame_object):
try:
return frame_object.f_locals[variable_name]
except KeyError:
try:
return frame_object.f_globals[variable_name]
except KeyError:
raise NameError(varname) from None
Run Code Online (Sandbox Code Playgroud)
但问题是关闭变量.据我所知,它们不存储在像本地和全局变量这样的字典中.更糟糕的是,如果函数实际访问它们,变量只会成为闭包变量(例如通过读取它的值_ = closure_var或者用它来写入它nonlocal closure_var; closure_var = _ …
The following code works in Python 2.7, to dynamically inject local variables into a function scope:
myvars = {"var": 123}
def func():
exec("")
locals().update(myvars)
print(var)
func()
# assert "var" not in globals()
Run Code Online (Sandbox Code Playgroud)
这有点微妙,但是exec语句的存在向编译器指示可以修改本地名称空间。在参考实现中,它将把名称“ locals”的查找从LOAD_GLOBAL op转换为LOAD_NAME op,从而允许添加到本地名称空间。
在Python 3中,它exec变成了函数而不是语句,并且该locals()调用返回了名称空间的副本,其中的修改无效。
您如何在Python 3中重新创建想法,以便在函数内部动态创建局部变量?还是仅在Python 2.x中才有“功能”?
注意:该代码不得在外部范围内绑定名称。
cpython ×10
python ×10
python-3.x ×3
c ×1
compilation ×1
distribution ×1
gil ×1
install ×1
math ×1
memory-leaks ×1
operators ×1
pypy ×1
python-2.7 ×1
python-3.7 ×1
python-c-api ×1
setup.py ×1
stack-frame ×1
twisted ×1