分类档案: 蟒蛇

避免使用顶级导入进行多次读取

最近我’我们一直在与需要导入大型JSON定义文件的各种应用程序一起使用,这些文件定义了复杂的应用程序设置。通常,代码库中的多个辅助模块都需要这些文件。所有软件工程原理都指向仅一次导入此类文件,无论使用了多少个辅助模块。

我的本能方法是在文件中读取一个主处理程序模块,然后将其内容作为类初始化参数传递:

主要_handler.py
蟒蛇
1
2
3
4
5
6
7
8
9
10
11
12
#main_handler.py
 
进口 json
 
模组1 进口 Class1
模组2 进口 Class2
 
打开(“ 设定.json”) f:
    设定 = json.加载(f)
 
在it1 = Class1(设定=设定)
在it2 = Class2(设定=设定)

这样做的问题是,如果您有一个复杂的导入过程,并且要导入多个文件,它可能会开始看起来很凌乱。我最近发现这种多重初始化参数方法不是’t实际上是必要的。

在Python中,您实际上可以在两个辅助模块(module1和module2)中导入相同的设置加载器模块,而python只会加载一次:

主要_handler.py
蟒蛇
1
2
3
4
5
6
7
#main_handler.py
 
模组1 进口 Class1
模组2 进口 Class2
 
在it1 = Class1()
在it2 = Class2()

模组1.py
蟒蛇
1
2
3
4
5
6
7
# 模组1.py
 
进口 设定_loader
 
Class1:
    定义 __在里面__():
        .设定 = 设定_loader.设定

模组2.py
1
2
3
4
5
6
7
# 模组2.py
 
进口 设定_loader
 
Class2:
    定义 __在里面__():
        .设定 = 设定_loader.设定

设定_loader.py
蟒蛇
1
2
3
4
5
6
7
#settings_loader.py
 
进口 json
 
打开(“ 设定.json”) f:
    打印 “正在加载设置文件!”
    设定 = json.加载(f)

现在,当我们在终端中对此进行测试时:

终端输出
贝壳
1
2
3
4
5
MRMAC:进口测试 脆弱的$
MRMAC:进口测试 脆弱的$
MRMAC:进口测试 脆弱的$ 蟒蛇 主要_handler.py
载入中 设定 文件!
MRMAC:进口测试 脆弱的$

尽管打电话 进口 设定_loader两次,Python实际上只调用了一次。这是非常有用的,但是如果您实际上想两次导入文件,也可能引起头痛。如果是这样,那么我会将设置导入器包含在 __在里面__()每个ClassX的实例并将其实例化两次。

在您的代码中模拟出API调用

使用任何积极开发的(python)编码项目,您都可以’re和您的团队每周将进行数百次相同的测试。如果有’向那里的任何第三方资源发出HTTP请求,这可能会导致问题。 API调用可能会很昂贵,过多地刮擦同一源可能会导致IP黑名单,并且调用可能会减慢整个测试过程的速度,从而给代码部署过程增加了负担。

为了解决这个问题,我们可以使用Python’的模拟库。模拟对于创建伪函数调用,伪类和其他可以返回伪值的伪对象非常有用。在大多数情况下,进行测试时,您实际上实际上是在测试应用程序如何解析数据,而不是第三方服务的可靠性。 API’的响应通常是相同的。模拟可以让您模拟API’响应并解析其数据,而不必每次都真正拨打电话。

It’设置起来非常棘手,所以我想我会写一个教程。情况设置有几个组成部分,但我’我会尽量解释一下。让’s说有一个提供一些有用的API响应的服务。那里’是一个由肯尼斯·雷茨(Kenneth Reitz)设置的网站HTTPBin,用于测试HTTP库,我们将在这里使用它。签出: //httpbin.org/ip内容如下:

的JavaScript
1
2
3
{
  “起源”: “ 123.123.123.123”,
}

让’s说我们的程序想获取IP地址中的 起源 领域。对–一个毫无意义的程序,但这类似于您的许多情况’ll encounter.

这里’是一个完全过度设计的类,无法从此服务获取数据。在类中初始化时 __在里面__,它将创建一个指向HTTPBin的base_url变量。主要的处理程序功能是 得到_ip功能,只需抓住那个领域’的内容。首先拨打电话 api_call 使用 请求.get 获取该HTTP数据。

my_module.py
蟒蛇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
要求 进口 得到
 
我的课:
    定义 __在里面__():
        .base_url = "//httpbin.org/ip"
 
    定义 api_call():
        “”“进行API调用”“”
 
        结果 = 得到(.base_url)
        如果 结果.:
            返回 结果.json()
 
        返回
 
    定义 得到_ip():
        “”“从API响应中获取语言”“”
 
        尝试:
            数据 = .api_call()
            返回 数据['起源']
         (TypeError, KeyError, IndexError):
            返回 “对{0}的HTTP请求失败”.格式(.base_url)

要简单地运行此代码(在Python 贝壳中):

1
2
3
4
>>> 进口 my_module
>>> 测试 = my_module.我的课()
>>> 测试.得到_ip()
u'123.123.123.123'

什么if we want 至 嘲笑 出 请求.get? 嘲笑模块文档尚不清楚如何在类中深入定位特定功能。事实证明,最简单的方法不是 魔术模拟 要么 返回_value 而是使用反直觉的命名“副作用”特征。这是测试模块的预模拟:

测试_my_module.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
进口 单元测试
 
my_module 进口 我的课
 
测试分类器(单元测试.测试用例):
    定义 设定():
        .ip_grabber = 我的课()
    
    定义 测试_ip_grabber():
        ip = .ip_grabber.得到_ip()
        .如sertIsInstance(ip, 基本串, “ 知识产权 应该是字符串”)
        .断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”)
 
如果 __名称__ == '__主要__':
    单元测试.主要()

如您所见,这是一组标准测试,用于检查 ip_grabber 函数返回有效的IP地址。它运行如下:

1
2
3
4
5
6
脆弱的$ 蟒蛇 测试_my_module.py
.
-----------------------------------
1 测试 0.293s
 

但是,这里的问题在于,每次运行测试时,它将调用实际的API。为了阻止这个,让’集成了模拟模块:

蟒蛇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
进口 单元测试
进口 嘲笑
 
my_module 进口 我的课
 
fake_get():
    定义 __在里面__(, 网址):
        . = 真正
    定义 json():
        返回 {'起源': '123'}
 
测试分类器(单元测试.测试用例):
    定义 设定():
        .ip_grabber = 我的课()
    
    @嘲笑.补丁('my_module.get', 副作用=fake_get)
    定义 测试_ip_grabber(, fake_get):
        
        ip = .ip_grabber.得到_ip()
        
        .如sertIsInstance(ip, 基本串, “ 知识产权 应该是字符串”)
        .断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”)
 
如果 __名称__ == '__主要__':
    单元测试.主要()

这里 we’ve:

  1. 导入了模拟模块。注意:如果您收到有关“wraps” 在 的 “six” 模组 的n it 是 almost certainly because you 有 more than 上e 在stallation 的 六 要么 嘲笑 和 上e needs 至 be deleted.
  2. 创建一个假函数 fake_get替换 请求.get 用。这实际上只是返回“123”现在,您可以在下面查看它如何使测试失败。
  3. 在test_ip_grabber函数周围添加了mock.patch包装器。这里非常重要的是指定函数名,因为它是在my_module中导入的,而不是在Python标准库中出现的;即我们正在做“my_module.get” rather than “requests.get”. 的 副作用 = 然后说用我们想要的任何功能替换它。
  4. 现在必须将副作用指定的伪造函数添加为该函数的参数。

运行此,我们得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
脆弱的$ 蟒蛇 测试_my_module.py
F
======================================================================
失败: 测试_ip_grabber (__主要__.测试分类器)
-----------------------------------
追溯 (最近 呼叫 持续):
  文件 “ /Library/Python/2.7/site-packages/mock/mock.py”, 线 1305, 修补
    返回 功能(*args, **钥匙war)
  文件 “ 测试_my_module.py”, 线 19, 测试_ip_grabber
    .断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”)
断言错误: 知识产权 应该 3
 
-----------------------------------
1 测试 0.002s
 
失败 (失败=1)

嘲笑’s 副作用 已取代 请求.get ðŸ™,要通过此操作,只需更换  返回 {'起源': '123'}返回 {'起源': '123.123.123.123'}再次运行:

1
2
3
4
5
6
脆弱的$ 蟒蛇 测试_my_module.py
.
-----------------------------------
1 测试 0.000s
 

测试通过和零HTTP流量! ðŸ™,

将HTML表转换为Excel下载HTTP响应:慢速OLAP DB连接的黑客

总览

善科 (“Good fox”日本)是一个报告系统(在这里查看Github上的代码) 一世’是在过去两周内在Mozilla创建的。基本上,我的非技术同事对Tableau感到非常沮丧(“INNER JOIN和OUTER JOIN有什么区别?”),我决定为他们创建一个简单的仪表板界面。

它是一个简单的引导程序前端,它包含数据库的活动统计信息 赞助瓷砖. 您 can drill down 至 每 tile or 客户/partner 和 pivot 通过 东西 like locale, 国家 和 日期.

善科’s堆栈(从高到低)

一项新功能

加载分析页面之一时,将显示一个表格。我的同事希望能够将数据下载到Excel。我想出了4种可能的方法来实现此目的:

  1. 只需重新运行查询,在后端将结果格式设置为csv,然后将其保存并在window.open()文件位置即可。
  2. 自动保存每个分析请求服务器请求中的数据,并定期清除旧文件。
  3. 使用像 ExcelBuilder
  4. Send 的 数据 back 至 的 server, 格式 it, 和 的n back 至 的 客户 via 一个 如果rame

哪个是最佳解决方案?

  1. 这是有问题的,因为我们的重点是查询速度。 redshift数据库是一个 OLAP面向列的数据库和仅追加。这意味着添加数据的速度非常快,但是查询速度却很慢(通常超过6秒)。是的,它正在处理数十亿行这样令人难解的行,但是就等待这么长时间的用户体验而言并不是那么好。’如果他们已经有数据,则要再等待6秒钟重新运行分析。
  2. 听起来这可能最终会在客户端上存储大量数据,但是效果很好。在安全性方面,我’我不确定数据应该留在用户身上’不需要PC。
  3. 这没有’t work 出 so well –在Firefox中,文件命名错误。将来,我’d根据分析参数命名文件,例如<client>-<date>-<country>.xls
  4. 这是最怪异的解决方案,但是它有效! 烧瓶在本地运行,因此运行速度非常快。具有文件许可权的JQuery / 的JavaScript并不会带来很多麻烦,而且您可以在服务器上轻松地操纵数据这一事实也很不错。

解决方案4

该过程如下“Download 对于 Excel” button 是 clicked:

  1. 使用JavaScript引用HTML表并将其转换为数组数组
  2. 将iframe附加到DOM
  3. 将带有POST操作和隐藏字段的表单附加到iframe
  4. 将表内容插入隐藏字段’s value
  5. 提交表格
  6. 让Flask接收POST请求并将信息格式化为CSV
  7. 返回带有包含CSV的文件附件的HTTP响应

让’s implement it

添加此功能以获取表内容并将其放入数组中
的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
功能 convert_table_to_array() {
//将当前表转换为列表列表
可耐 = 文件.得到ElementById(“ impressions_table”) //该表在zenko中将始终称为this
//将表格转换为列表列表(即数组数组)
变种 数据 = [];
//元数据
col_count = 可耐.孩子们[0].孩子们[0].孩子们.长度 //列数
行_count = 可耐.孩子们[1].孩子们.长度 //行数
//获取标题(即包含列标题的第一行)
标头_cells = 可耐.孩子们[0].孩子们[0].孩子们
标头 = []
对于 (i=0;i<标头_cells.长度;i++) {
标头.(标头_cells[i].textContent)
}
数据.(标头)
//遍历每一行
行_cells = 可耐.孩子们[1].孩子们
对于 (i=0;i<行_cells.长度;i++) {
= 可耐.孩子们[1].孩子们[i].孩子们
//获取行中的每个单元格
行_content = []
对于 (j=0;j<.长度;j++) {
cell_content = [j].textContent.更换(“,”, ) //some textual entries already contained a comma which messed 与 东西
行_content.(cell_content)
}
数据.(行_content)
}
返回 数据
}

在JQuery中,有多种方法可以使用 可重复的.()但是我遇到了麻烦,使用.children来简单地引用细胞要容易得多。

这就是所谓的按钮单击事件
的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
功能 download_xls() {
//将当前表下载为excel文件
 
//1. Create 一个 如果rame
如果rame = 文件.createElement(“ 如果rame”)
如果rame.setAttribute(“宽度”, 1)
如果rame.setAttribute(“高度”, 1)
如果rame.setAttribute(“框架边框”, 0)
如果rame.setAttribute(“ src”, “关于:空白”)
 
//2. Create a 形成 that can send 数据 至 烧瓶
形成 = 文件.createElement(“形成”)
形成.setAttribute(“方法”, “ POST”)
形成.setAttribute(“行动”, “ / download_excel”)
 
//3. Put 的 table 数据 整型o a hidden field 在 that 形成
数据 = 文件.createElement(“输入”)
数据.setAttribute(“类型”, “隐”)
数据.setAttribute(“值”, convert_table_to_array())
数据.setAttribute(“名称”, “数据”)
//4. Append 的se new elements 至 的 DOM
形成.附加Child(数据)
如果rame.附加Child(形成)
文件.身体.附加Child(如果rame)
//5. Send 的f 的 数据
形成.提交()
}

然后,(本地运行中的)Flask将在以下位置接收POST请求: /download_excel一种 。 让’s set up 的 路线:

烧瓶路线
蟒蛇
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#接受POST数据(大于GET数据)
@应用程式.路线('/ download_excel', 方法=['得到', 'POST'])
定义 download_excel():
“”“根据收到的帖子信息创建文件下载”“”
#POST数据可通过request.form上的字典进行访问
数据 = 请求.形成[“数据”]
数据 = 数据.分裂(“,”) #以逗号分隔
#数据是列表的列表,例如[[1,2],[3,4]],但不幸的是发送了
#如  [1,2,3,4]。但是,我们知道有6列,因此我们可以将其拆分
#up 整型o 六es 与 a 清单 comprehension
数据 = [数据[x:x+6] 对于 x Xrange(0, (数据), 6)]
#N现在每个人都用逗号重新加入,所以它很csv-ish
数据 = “ \ n”.加入([','.加入(x) 对于 x 数据])
响应 = make_response(数据)
#返回带有附件的HTTP响应
响应.标头[“内容处置”] = “附件;文件名= 数据.csv”
返回 响应

现在,当用户单击按钮时:

下载Excel链接

他们立即得到:

下载弹出窗口

对不起,我可以’无法显示Excel中的数据,因为数据不是 ’目前还没有公开。所有代码均可用 在github上!

然而,一件奇怪的事情是表格没有’t出现在检查器中(在Chrome或Firefox中):

在检查器中不可见

不过,您可以使用一些相当长的吸气剂来访问它:

why.jpg

未来功能 

  • 这些文件的名称可能比data.csv更直观。– perhaps a combination 的 变种ious 东西 seen 在 的 URL’s query 串
  • 可容纳超过6行的表格。使用不同的定界符(例如,“###”.
  • Create 一个 .xls 文件 rather than a CSV, 如果 的re 是 一个y advantage

MongoDB阿司匹林

基本上,这是我使用Mongo时遇到的常见错误/任务/问题列表。一世’我记下了通常有效的方法。可能是你’会发现它很有用ðŸ™,

为什么我的远程mongodb连接被拒绝了?

1
2
3
4
pymongo 进口 MongoClient
c = MongoClient(“某些IP地址”)
...
pymongo.错误.连接失败: 可以 连接 123.456.0.1:27017: [Errno 111] 连接 被拒绝

    • 删除 蒙哥.从您的主要mongodb存储文件夹中选择文件,然后重新启动[所以]
    • 如果使用redhat,请检查  塞斯塔图斯
    • 修改 /等等/系统配置/iptables按照以下说明具有正确的防火墙规则 蒙哥b文档.

您如何在pymongo中遍历所有mongoDB集合? 

我通常将集合作为对象属性来访问,例如:  康恩.数据库.采集.找一个()但实际上,数据库和连接也可以作为字典中的键来访问:

1
2
3
4
5
6
7
8
9
10
11
pymongo 进口 MongoClient
康恩 = MongoClient() #使用它代替Connection()
 
这里使用#[1:]是因为第一个集合是system.indexes
对于 采集 康恩.数据库.采集_names()[1:]:
    #做点什么
    康恩.数据库[采集].找一个()
 
#我们可以这样说:
康恩['数据库'].采集.找一个()
康恩.数据库['采集'].找一个()

为什么mongod每当我关闭外壳时都会终止?即使使用 &最后

启动mongod时,请使用 蒙哥 -叉子Â(注意:fork必须在mongod一词之后),它将作为后台进程启动。或者只是添加 叉子 = 真正到您的配置。

我刚刚创建了一个经过身份验证的数据库,并且可以’t even 我们e 节目 数据库一种 !

创建具有以下所有4个权限的新用户:userAdminAnyDatabase,readWriteAnyDatabase,dbAdminAnyDatabase,clusterAdmin:

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
> D b.添加用户({ 用户: “ hilarious_name” , 密码: “值得纪念的”, 角色: ['clusterAdmin','userAdminAnyDatabase', 'dbAdminAnyDatabase' 'readWriteAnyDatabase'] } )
{
        “用户” : “ hilarious_name” ,
        “ 密码” : “ 0c3032130d7123a36c1913b2f55a3c84”,
        “角色” : [
                “ clusterAdmin”,
                “ 用户AdminAnyDatabase”,
                “ readWriteAnyDatabase”,
                “ D bAdminAnyDatabase”,
        ],
        “_ID” : 对象编号(“ 535956f010b65cad1f7906f7”)
}

OrderedDict的快速解决方案’O(1)索引查找在Python中的限制

问题的背景

我定期处理巨大的机器学习数据集。一种非常通用的格式,用于 威卡 是 “ARFF”(属性关系文件格式)。这本质上创建了一个结构良好的丰富CSV文件,可以轻松地在Logistic回归,决策树,SVM等中使用。为了解决CSV数据非常稀疏的问题,有一种稀疏的ARFF格式可以让用户转换稀疏的行在每个文件中,例如:

f0 f1 f2 f3 fn
1 0 1 0 0

进入更简洁的版本,其中您具有功能列表,只需指定功能’的索引和值(如果有):

@ATTRIBUTE f0数值
@ATTRIBUTE f1数值
@ATTRIBUTE f2 NUMERIC
@ATTRIBUTE f3 NUMERIC

@属性fn数字
@数据
{0 1,2 1}

{feature-index-zero为1,feature-index-two为1}, 只需忽略所有零值。

实施问题

如果您有4个功能,这很容易,但是如果您有超过100万个功能并且需要找到每个功能的索引,该怎么办?在列表中搜索特征是O(n),并且如果您的训练数据也很大,那么创建稀疏的ARFF将会非常低效:

1
2
3
4
5
6
7
8
9
特征 = ['名称', 'some_metric', “ 一个_attribute”, 'some_boolean']
 
#搜索特征的存在为O(n)
>>> 'some_metric' 特征
真正
 
#检索列表中要素的索引也是O(n)
>>> 特征.指数('some_metric')
1

我以为可以通过使用OrderedDict来改善这一点。很简单,这是一个维护其项目顺序的字典–因此您可以以类似堆栈的方式从最后弹出()项目。但是,之后 关于StackOverflow的一些研究,这令人失望’包含任何有效的方法来计算键的索引:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
馆藏 进口 OrderedDict
特征 = ['名称', 'some_metric', “ 一个_attribute”, 'some_boolean']
od = OrderedDict()
对于 f 特征:
    od[f] = 0
 
#搜索特征的存在为O(1)
>>> 'some_metric' od
真正
 
#尽管检索列表中要素的索引仍然是O(n)!
>>> 特征.().指数('some_metric')
1
#keys()必须创建内存中所有键的完整列表,才能
#retrieve 的 指数. 您 可以 我们e iterkeys() 至 improve memory
#performance,但仍然很可笑。

解决方案

什么can we do about this? Enter my favorite 事情 ever, 定义aultdicts 与 拉姆达s:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
馆藏 进口 定义aultdict
特征 = ['名称', 'some_metric', “ 一个_attribute”, 'some_boolean']
dd = 定义aultdict(拉姆达: (dd))
 
对于 f 特征:
    dd[f] #不需要给它一个值,只需要调用它
 
#所以现在我们可以在O(1)中进行查找
>>> 'some_metric' dd
真正
 
#并在O(1)中获得其索引
>>> dd['some_metric']
1

稍微修改一下lambda,除了索引之外,分配项目值也很简单:

1
2
3
4
5
6
7
8
9
10
11
dd = 定义aultdict(拉姆达: {'指数':(dd)})
 
#然后可以无缝添加更多信息:
 
dd['some_metric']['信息'] = 1
dd['some_attribute']['信息'] = 2
 
#保持自动生成索引的O(1)查找:
 
>>> dd['some_attribute']['指数']
1

 局限性

这是一个有趣的修复程序,但没有’支持完整的词典功能– deleting 项目s won’重新排序索引,您可以’轻松地依次进行迭代。但是,由于在创建此ARFF文件时,’无需删除或迭代’s 不 a problem.

在哈佛用软件木工教授Python

BScO7AGIMAAvVZj.jpg-中

Mike用Python教Hamlet。照片版权Chris Erdmann: //twitter.com/libcce/status/371281901191196672

I’是纽约市名为Software Carpentry的组织的一部分。它使用志愿者向大学,大型政府组织和其他感兴趣的人群教授不同级别的编程。我之前曾在哥伦比亚大学任教,上周末在哈佛大学举办,由 克里斯·埃德曼,哈佛-史密森天体物理学中心的首席图书馆员。

在使用Software Carpentry之前,我的教学经验仅限于向亲朋好友讲解编程方面的内容,以及在日本为儿童和成人教英语和法语的一年时间的一部分。教学很难。它’批评老师很容易– I’我经常发现自己是如此,而没有考虑将复杂的概念传达给一群背景和动机各不相同的学生的努力和压力。一世’ve从我最近的两次SWC活动中得出了有关如何优化教学风格的一些结论:

星期六’s Teacher 线-up

运作良好的事情

  • 幽默。迈克在教程中撒了一些有趣的轶事,这使全班都很活跃。
  • 相关和有趣的主题。哈姆雷特(Hamlet)是一个不错的选择,因为面向图书管理员的观众也喜欢在拼字游戏中作弊。字典带来了几个有趣的条目,例如:  grep “。* s。* s。* s。* s。* s。* s” |
  • 添加轶事来拯救人们谷歌搜索。我认为很多程序员’他们的活动仅仅是寻找一个’已经完成了您想做的事情,并做了一些修改–或连接构建块。因此,在结束时谈论诸如 附加()VS与加号等串联 第一+第二 , I mentioned 东西 like 双端队列()和  格式()一种 。

下次要记住的事情

  • 慢慢打字。我在MongoDB上工作很多,所以最终从 pymongo 进口 连接; c = 连接()  20+ times a day 整型o 的 terminal. This can become so fast, 东西 like that can seem bewildering 至 newcomers.
  • 使用带有大字体和昏暗灯光的高对比度终端,使其从房间的背面超级容易看清。

什么can advanced programmers 得到 出 的 教学 such basic 东西?

  • 您’从老师和学生那里学到很多东西’s questions
  • 社区参与是简历中的一项重要资产,它向潜在的雇主表明您有能力/有能力培训未来的同事
  • 当在社会或商业上向非技术人员解释技术问题时,它有助于在教学过程中掌握现有的类比和轶事。
  • 您’会遇到许多志同道合的人,参与社区的感觉很棒。

什么did I learn?

  • 要求 图书馆。我通常使用 网址lib2 从网页抓取HTML。事实证明,Urllib2只是一个用于HTTP请求的可扩展性更大的库,如下所示 stackoverflow说明.
  • 有关Git的更多信息。我在工作中使用SVN,因此不要’真的向github提交任何东西。 Git很难。 Erik是一位出色的讲师,从容不迫地从基础知识过渡到了.gitignore和diff之类的细节。
  • 什么“immutable” really means. I hear this thrown around quite a lot 和 it basically just means 东西 can’被分配给一个对象。例如。的。 分裂()myString.分裂()可以’t成为变量。非常简单。

When 文字评估 fails: 我们ing ASTerisk 不ation 至 read 在 a 日期time object

蟒蛇中的一项重要功能是 AST((抽象语法树) 图书馆’s 文字评估一种 。这使您可以读取python数据类型的字符串版本:

1
2
3
4
5
6
7
8
9
>>> AST 进口 文字评估
>>> #带有一些琐碎信息的示例字典
>>> myDict = “ {'someKey':1,'otherother':2}”
>>> #让我们使用函数进行解析
>>> 测试Eval = 文字评估(myDict)
>>> 打印 测试Eval
{'someKey': 1, “ otherKey”: 2}
>>> 类型(测试Eval)
<类型 'dict'>

像这样导入字典类似于 解析JSON 使用Python’s  json.负载解码器。但是它也有缺点’s 的 JSON’s restrictive 数据types, 如 we can see here when 的 字典ionary contains, 对于 example, a 日期time object:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> myDict = "{'someKey': 1, 'rightNow': 日期time.datetime(2013, 8, 10, 21, 46, 52, 638649)}"
>>>
>>> 文字评估(myDict)
追溯 (最近 呼叫 持续):
  文件 "<stdin>", 线 1, <模组>
  文件 “ /root/anaconda/lib/python2.7/ast.py”, 线 80, 文字评估
    返回 _兑换(节点_or_string)
  文件 “ /root/anaconda/lib/python2.7/ast.py”, 线 63, _兑换
     压缩(节点., 节点.价值观))
  文件 “ /root/anaconda/lib/python2.7/ast.py”, 线 62, <基因>
    返回 字典((_兑换(k), _兑换(v)) 对于 k, v
  文件 “ /root/anaconda/lib/python2.7/ast.py”, 线 79, _兑换
    提高 ValueError(“格式错误的字符串”)
ValueError: 畸形的

因此,您可以尝试编写一些代码来自己解析字典数据类型。这变得非常棘手,但是最终您可能可以容纳所有常见的数据类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
定义 read_dict(d):
    “接受包含字典的字符串。
    试图对此进行解析并返回字典。”
    parsed_dict = {} #结果
    #删除{}并分成大块
    d = d[1:-1].分裂(',')
    #遍历大块并尝试解释它们
    对于 kv_pair d:
        #由中央结肠分裂
        kv_pair = kv_pair.分裂(“:”)
        #解释键和值
        k = 我是什么(kv_pair[0])
        v = 我是什么(kv_pair[1])
        #添加到最终解析的字典中
        parsed_dict[k] = v
    返回 parsed_dict
 
定义 我是什么(事情):
    “解释字符串的简单尝试
    数据类型。可以处理字符串和整数”
    #删除任何反引号
    如果 事情.以。。开始(“”) 要么 事情.以。。开始(“”):
        事情 = 事情[1:-1]
 
    #Now检查数据类型(尽管还有更多方法)
    如果 事情.等轴():
        返回 整型(事情) #返回数字
    其他:
        返回 事情 #返回字符串
    #如果任何一个都无法识别,则返回错误
    返回 “数据损坏”

但这仍然没有’t truly fix our 日期time object problem:

1
2
3
4
5
>>> read_dict(myDict)
追溯 (最近 呼叫 持续):
  文件 "<stdin>", 线 1, <模组>
  文件 "<stdin>", 线 13, read_dict
IndexError: 清单 指数 范围

Which 是 where we 得到 至 的 crux 的 this post. I thought at 第一 that I 可以 deal 与 日期time’通过提取类来格式化  日期time.日期time(2013, 8, 10, 21, 46, 52, 638649) as a tuple 通过 spotting 的 brackets, 的n feeding 的 tuple back 整型o 日期time like: 

1
2
3
4
5
>>> x = (2013, 8, 10, 21, 46, 52, 638649)
>>> parsedDate = 日期time(x)
追溯 (最近 呼叫 持续):
  文件 "<stdin>", 线 1, <模组>
TypeError: 一个 整数 需要

但显然不是。必须提取元组–不是通过lambda或列表理解,而是实际上使用星号表示法:

1
2
3
>>> parsedDate = 日期time(*x)
>>> 打印 parsedDate
2013-08-10 21:46:52.638649

星号(*)将x等可迭代程序解压缩为该函数的位置参数。简单!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
定义 我是什么(事情):
    “解释字符串的简单尝试
    of a 数据type. Can deal 与 str, 整型, 日期time"
    #删除任何反引号
    如果 事情.以。。开始(“”) 要么 事情.以。。开始(“”):
        事情 = 事情[1:-1]
 
    #现在检查某些数据类型
    如果 事情.等轴():
        返回 整型(事情) #返回数字
    小精灵 事情.以。。开始('约会时间'):
        #获取括号之间的数字
        事情 = 事情.分裂('(')[1].分裂(')')[0]
        #parse 的 digits, unpack 整型o 日期time 和 返回
        返回 日期time(*[整型(x) 对于 x 事情])
    其他:
        返回 事情 #返回字符串
    #如果任何一个都无法识别,则返回错误
    返回 “数据损坏”

使用ACORA一次处理数百个停用词

“80%的数据分析是花费在清洁数据上,其中20%的花费是在抱怨清洁数据” – 长社大数据宝

这是我听到的最好的报价之一 PyData 2013。当处理大量数据时,通常只有一小部分与一个数据相关’的分析,尝试清洁它可能会很痛苦。但这也是 基本阶段, 所以让’使它尽可能的无痛。

一个示例是巨大的日志文件。说我们’重新处理多TB的Apache日志文件,如下所示:

1
2
3
4
5
6
7
8
9
10
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-dropdown.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-scrollspy.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-tab.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-tooltip.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-popover.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-button.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-collapse.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-carousel.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:38 -0500] “获取/static/js/bootstrap-typeahead.js HTTP / 1.1” 304 - "http://127.0.0.1/" “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”
127.0.0.1 - - [17/七月/2013:07:22:39 -0500] “ GET /favicon.ico HTTP / 1.1” 404 4025 “-” “ Mozilla / 5.0(Macintosh;英特尔Mac OS X 10_7_4)AppleWebKit / 537.36(KHTML,例如Gecko)Chrome / 28.0.1500.71 Safari / 537.36”

这是包含数千行的有用数据,我们’d想使用 我之前提到的大文件处理脚本。但是,有些行’不关心–所以你可以写一个简单的条件:

1
2
3
4
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        如果 “ some_keyword” 线:
            做点什么()

什么if you 有 2 东西 that you don’t want 在 每 线?

1
2
3
4
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        如果 (“ some_keyword” 线) (“ other_keyword” 线):
            做点什么()

什么if you 有 3 东西 that you don’t want 在 每 线?

1
2
3
4
5
6
7
8
9
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        线_is_ok = 真正
        对于 停用词 [“ some_keyword”, “ other_keyword”, “不”]:
            如果 停用词 线:
                线_is_ok =
                打破 #退出循环
        如果 线_is_ok: #仅在line_is_ok未被篡改的情况下处理行
            做点什么()

但这变得超级低效,有点愚蠢。每个额外的关键字都需要通过该行。使用此代码,基本上所有情况都是最坏的情况。

带上ACORA!

阿科拉 是Stefan Behnel’的库基于 Aho-Corasick字符串匹配算法。无需深入了解其背后的数学原理,它基本上会将您拥有的所有停用词都编译为单个¼-停用词,这意味着在您的日志文件行中对该停用词进行一次扫描将检查所有停用词。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
阿科拉 进口 AcoraBuilder
 
#创建停用词列表-这些是条目
#我们想忽略的
停用词 = ['.js', '.ico', '.css', '.jpg', ...]
 
#将它们输入新的Acora Builder中
停用词_matcher = AcoraBuilder()
对于 停用词 停用词:
    停用词_matcher.(停用词)
 
#now让它构造超级停用词
停用词_matcher = 停用词_matcher.建立()
 
#this使用生成器迭代匹配项
#发现任何东西都会停止
对于 比赛 停用词_matcher.寻找者(线_from_log_file):
    打印 “找到匹配:{0}”.格式(比赛)

但是我们如何将其从以前集成到行扫描器中呢?像这样!

1
2
3
4
5
6
7
8
打开('mylogfile.txt', 'r') f:
    对于 线 f:
        线_is_ok = 真正
        对于 比赛 停用词_matcher.寻找者(线):
            线_is_ok =
            打破 #退出循环
        如果 线_is_ok:
            做点什么()

We’ve用单个ACORA匹配器替换了整个多个停用词匹配的for循环。

性能说明

阿科拉很棒,但是如果只有几个停用词或只有几行,性能可能会下降。当您有大约20个以上的停用词并且至少有1000个左右的日志文件行要扫描时,它的性能最佳。

提取TLD(顶级域)–和怪异的怪癖会让你不高兴

I’ve been 我们ing 约翰·库科夫斯基‘优秀的Python域提取库“葡聚糖”最近,TLDextract可以很容易地从URL中提取域名,例如:

1
2
3
>>> 葡聚糖 进口 提取
>>> 提取('http://stjamespublichouse.com/?p=106')
提取结果(子域='', ='ikigomu', 顶级域名='com')

为什么这有用?

这有很多应用–例如,如果您要创建链接到您网站的热门域名的摘要,则可能会有很多引荐网址:

1
ref_urls = ["http://www.google.com/somesearch", "http://sub.othersite.com/something", "//www.google.com/images", "http://xyz.yahoo.com/sample"] #etc等

您可以编写一些简单的代码来输出域:

1
2
3
4
5
6
7
8
9
葡聚糖 进口 提取
 
定义 抢域(网址):
    “返回URL的域”
    尝试:
        网址 = 提取(网址)
    例外:
        提高 例外(“此URL不起作用:{0}”.格式(网址))
    返回 '。'.加入((网址[1], 网址[2])) #连接域名和tld

并使用 词频计算器 从我以前的帖子中汇编出最热门的引用域名列表!看到我’ve修改了第10行,改为将域添加为键:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
算子 进口 项目获取器
馆藏 进口 定义aultdict
 
定义 域_frequencies(l):
    “获取网址列表'l'并返回列表清单
      其中每个项目是[域,频率],已排序
       descending."
    all_freqs = 定义aultdict(整型) #暂时保存值
    对于 项目 l:
        all_freqs[抢域(项目)] + = 1 #将域添加到defaultdict
    #将字典转换为列表列表
    all_freqs = [[k,v] 对于 k,v all_freqs.重复项()]
    #返回排序后的版本
    返回 已排序(all_freqs, =项目获取器(1), 逆转=真正)

哪个返回:

1
2
>>> 域_frequencies(ref_urls)
[[“ google.com”, 2], [“ yahoo.com”, 1], [“ othersite.com”, 1]]

为什么可以’你在第三个斜杠处用句号分隔’s before?

这是我一开始尝试做的事情:

1
2
3
4
5
定义 抢域(网址):
    返回 网址.分裂('/')[2].分裂('。')[-2:]
 
>>> 抢域("http://www.google.com/something")
>>> ['谷歌', 'com']

但由于域名系统是顶级域名(例如.com),二级域名(例如.gov.uk),标准子域名(egiimgur.com)和句号过多的人(例如www.dnr。 state.oh.us)变得更加棘手,无法容纳所有内容。因此TLDextract实际上维护着Mozilla的本地副本’您系统上的ICANN域的列表,从以下位置下载: 

http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1

并从中基本上找到URL末尾的匹配项。非常好!

所以呢’标题中提到的问题?

不幸的是,使用Mozilla的警告’的清单是您得到一些看似奇怪的行为。有许多网站和公司从亚马逊请求其子域为TLD,并包含在列表中:

的JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Amazon CloudFront : //aws.amazon.com/cloudfront/
//由Donavan Miller请求<[email protected]> 2013-03-22
云前.
 
// Amazon Elastic Compute Cloud: //aws.amazon.com/ec2/
//由Osman Surkatty请求<[email protected]> 2013-04-02
计算.亚马逊.com
我们--1.amazonaws.com
计算-1.amazonaws.com
z-1.计算-1.amazonaws.com
z-2.计算-1.amazonaws.com
ap-东北-1.计算.amazonaws.com
ap-东南-1.计算.amazonaws.com
ap-东南-2.计算.amazonaws.com
欧盟-西方-1.计算.amazonaws.com
SA--1.计算.amazonaws.com
我们-政府-西方-1.计算.amazonaws.com
我们-西方-1.计算.amazonaws.com
我们-西方-2.计算.amazonaws.com
 
// Amazon Elastic Beanstalk : //aws.amazon.com/elasticbeanstalk/
//由Adam Stein请求<[email protected]> 2013-04-02
弹豆.com

要DynDNS的东西:

的JavaScript
1
2
3
4
5
6
7
8
9
--认证的.com
-已保存.组织
-圆滑的.com
-优步.com
-非常-.组织
-非常-邪恶.组织
-非常-.组织
-非常-不错.组织
-非常-.组织

和更多… So you’如果您输入以下内容,将会绊倒:

1
2
>>> 提取("//scriptgang.elasticbeanstalk.com/getMagazine.html")
提取结果(子域='', ='脚本帮', 顶级域名='elasticbeanstalk.com')

而不是预期的“.com” 如 的 顶级域名.

简洁的方式来构建可迭代的Python频率表

这是编程中一个有趣且经常解决的任务,在NLP和数据科学中尤其普遍。通常有一个清单“things”有很多重复,并想知道哪些是最受欢迎的。

资料范例

1
我的清单 = [1,1,1,1,5,5,5,3,2,2,2,3,4,5,5,5,5,5,5,6,6,6,6]

要么:

1
my_sentence = “猫坐在垫子上看报纸”

哪个最受欢迎的号码?最受欢迎的字母是哪一个?

编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
馆藏 进口 定义aultdict
算子 进口 项目获取器
 
定义 freq_table(l):
    “获取列表'l'并返回列表列表
      每个项目都是['item',frequency],已排序
       descending."
    all_freqs = 定义aultdict(整型) #暂时保存值
    对于 项目 l:
        all_freqs[项目] + = 1 #添加到字典
    #将字典转换为列表列表
    all_freqs = [[k,v] 对于 k,v all_freqs.重复项()]
    #返回排序后的版本
    返回 已排序(all_freqs, =项目获取器(1), 逆转=真正)

对于我们的数据,我们现在得到:

1
2
>>> freq_table(我的清单 )
[[5, 9], [1, 4], [6, 4], [2, 3], [3, 2], [4, 1]]

所以5是最受欢迎的项目,有9个出场。

1
2
>>> freq_table(my_sentence)
[['', 9], ['一种', 7], ['e', 5], ['t', 4], ['n', 3], ['d', 2], ['H', 2], ['p', 2], [, 2], ['r', 2], ['C', 1], ['m', 1], ['o', 1], ['T', 1], ['w', 1]]

因此,空间是最受欢迎的,其次是a,e和t。