第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

詭異的 list comprehension 展開(kāi)

標(biāo)簽:
大數(shù)據(jù)

问题描述

存在一些文件名类似 2016-07-16_161.res 2016-07-18_161.res 的文件,文件内容如下:

less 2016-07-16_161.res
1.34.0.68
1.34.1.37
1.34.1.121
1.34.5.87
1.34.5.182
1.34.6.72
1.34.6.245
1.34.9.149
1.34.11.74
1.34.13.161
...

希望通过 Spark 统计出存活超过 n 天的 IP,并可以同时看到该 IP 分别在哪天存活。

因此需要先将这些文件转换成 Pair RDD,其中的每一项以 IP 为 key,以日期为 value。

编写 Spark 脚本如下:

rdds = [sc.textFile(f).map(lambda x: (x, f.split('_')[0])) for f in glob('*.res')]

预期得到结果:

rdds[0].first()
(u'210.240.117.126', '2016-07-16')

rdds[1].first()
(u'210.240.117.126', '2016-07-18')

但实际得到的结果为:

rdds[0].first()
(u'210.240.117.126', '2016-07-18')

rdds[1].first()
(u'210.240.117.126', '2016-07-18')

即所有的 RDD 中每一项的 value 都为同一值。

问题定位

看到这个现象基本把可能出问题的点锁定在了 map(lambda x: (x, f.split('_')[0])) 附近。

查找了 pyspark 中 map 函数的实现,也没发现有什么不妥的地方。rdd.py 中 RDD::map() 的实现如下:

    def map(self, f, preservesPartitioning=False):
        """
        Return a new RDD by applying a function to each element of this RDD.
        >>> rdd = sc.parallelize(["b", "a", "c"])
        >>> sorted(rdd.map(lambda x: (x, 1)).collect())
        [('a', 1), ('b', 1), ('c', 1)]
        """
        def func(_, iterator):
            return map(f, iterator)        return self.mapPartitionsWithIndex(func, preservesPartitioning)

另一个值得怀疑的点就是 lambda 的行为是不是真的符合预期,但是一直只是怀疑,没有找到有效的方法来验证自己的猜测。直到看了 @张通 转发的 《Python 中的 lambda 和「真正的」lambda 有什么区别?》[1],才确认并搞清楚问题发生的根本原因。

问题发生的根本原因在于 Python 中的 lambda 在实现上存在缺陷[2],导致 Spark 脚本中传入 map 函数的 lambda 表达式共享了同一个变量 f,从而导致了上述问题的发生。

举一反三

目前大概可以确定,Python 实现的 lambda 表达式中的变量可能并不像正常的函数那样具有独立的作用域。

以下述代码为例:

test = [lambda x: x+i for i in range(10)]print test[0](1)print test[9](1)

这段代码并不会如预期的输出 110,而是会输出 1010。使用 dis 模块分析列表中的任意一个 lambda 表达式得到如下结果。

In [3]: dis.dis(test[0])  1           0 LOAD_FAST                0 (x)              3 LOAD_GLOBAL              0 (i)              6 BINARY_ADD              7 RETURN_VALUE

从上述 Python bytecode 中可以看出 lambda 表达式中的变量 i 的确没有一个独立的作用域,而是使用了相对全局的作用域,而此时该作用域中的变量 i 已经变成了 9,因此得到了上述结果。

更近一步,list comprehension 中的变量的作用域又是怎样的呢?是仅仅作用于 list comprehension 内部,还是也会影响到外部呢?

实测代码如下:

In [13]: p = 100In [14]: a = [p for p in range(10)]

In [15]: print a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [16]: print p9

可见 list comprehension 中的变量也会对其外的变量产生影响,即 list comprehension 中的变量也不具有独立的作用域。所以,虽然 list comprehension 具有执行效率高和可读性强等优点,在实际的编码中也需要多注意这些副作用,防止被坑。

问题解决

下面两个方法均可解决该问题:

def gen_rdd(f):
    return sc.textFile(f).map(lambda x: (x, f.split('_')[0]))
    
rdds = [gen_rdd(f) for f in glob('*.res')]
rdds = map(    lambda f: sc.textFile(f).map(lambda x: (x, f.split('_')[0])), glob('*.res')
)

推荐使用第二种方式。



作者:DragonKid
链接:https://www.jianshu.com/p/17926082e1a3

點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺(jué)得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫(xiě)下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開(kāi)微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消