【问题标题】:Use line from text file as data for function使用文本文件中的行作为函数的数据
【发布时间】:2013-12-18 00:56:45
【问题描述】:

我对此完全陌生,所以请原谅我缺乏理解。

我想要 ulitmatley 做的是从文件中获取一行文本,然后将其放入 url(已经有该代码并理解),这将给出一个结果。加载后需要删除文本文件中的值。这是我目前所拥有的,用于使用 instagram API 查找 instagram 照片的脚本。

import time, random
import urllib,json,urllib2

def getuserId(userId):
userId_Dict = {}
try:
    list_of_users = open('superlikelist.txt', "r")
    for line in list_of_users:
        print line

    return userIdlist

我稍后会为此使用定义的值

def userspics(userId):
numuserspics=0
urlUserMedia = "https://api.instagram.com/v1/users/%s/media/recent/?access_token=%s" % (getuserId,auth_token)
values = {
          'client_id' : client_id}    
try:
    print urlUserMedia
    data = urllib.urlencode(values)
    req = urllib2.Request(urlUserMedia,None,headers)
    response = urllib2.urlopen(req)
    result = response.read()                      
    dataObj = json.loads(result);
    picsForUser = random.randint(1, 3)
    print "Pics for user %s" % (picsForUser, userId)
    countPicViews=0
    for picture in dataObj['data']:
        countPicViews = countPicViews+1
        numLikesFollows = numLikesFollows+1
        if(countPicViews == picsToLike):
            break
except Exception, e:
    print e

【问题讨论】:

    标签: python json api instagram


    【解决方案1】:

    从文本文件开头删除一行的唯一方法是重写整个文件,跳过该行。你可以在 Python 中做到这一点,或者使用像 sed 这样的外部工具,但无论你做什么,都会发生。


    正如 Eli 所说,最好先将项目复制成某种允许随机访问修改的格式。例如,您可以使用dbm 数据库。 (当然,dbm 的作用类似于字典,而不是集合……但您始终可以使用具有无意义值的字典来模拟集合。)

    首先,使用此脚本将平面文本文件转换为数据库:

    from contextlib import closing
    import dbm
    db = dbm.open('superlikelist.db', 'n')
    with open('superlikelist.txt') as f, closing(db):
        for line in f:
            dbm[line] = ''
    

    现在,你可以这样做了:

    from contextlib import closing
    import dbm
    
    def process_everything():
        db = dbm.open('superlikelist.db', 'w')
        with closing(db):
            for url in db.keys():
                do_something_with(url)
                del db[url]
    

    如果您坚持使用文本文件,另一种选择是避免一遍又一遍地重写文件,而只是在单独的位置跟踪读取的最后一个行号。像这样:

    def process_file():
        try:
            with open('lastread.txt') as lr:
                lastread = int(lr.read())
        except:
            lastread = -1
        with open('superlikelist.txt') as f:
            for i, line in enumerate(file):
                if i > lastread:
                    do_stuff_with(line)
                    with open('lastread.txt', 'w') as lr:
                        lr.write(str(lastread))
    

    如果您出于某种原因必须重写原始文件,您至少可以避免为每一行重写它,而只需在进程结束时重写一次。显然,即使过程结束,例如,当您只完成一半时用户按下 control-C,您也希望确保发生这种情况,但您可以使用try/finally 来处理它或atexit。 (当然,如果有人拔掉计算机上的插头,这将无济于事……但如果有人在你重写整个文件时拔掉插头,你会遇到一个更更糟糕的问题。而且这种变化降低了该问题的可能性。)所以:

    import os
    
    def process_file():
        with open('superlikelist.txt') as f:
            try:
                for line in f:
                    do_stuff_with(line)
            finally:
                with open('superlikelist.new', 'w') as fout:
                    fout.writelines(f)
                os.rename('superlikelist.new', 'superlikelist.txt')
    

    这是一个有点 hacky 的实现。首先,您可能想要使用例如tempfile.NamedTemporaryFile 而不是硬编码名称。其次,在 Windows 上,如果其中一个文件是打开的,则不能只将一个文件移到另一个文件上;事实上,真的没有“原子地”替换文件的好方法。您可以做的最好的事情是跟踪临时文件的名称,然后在关闭这两个文件后尽快os.remove('superlikelist.txt') 然后执行rename

    【讨论】:

      【解决方案2】:
      1. 我不建议这样做。这不是文件 IO 的用途。从队列或数据库中读取项目并在处理每个项目时删除它们会更好。
      2. 如果您必须这样做,事情会变得有点混乱,而且绝对不是 Python 的,但它会起作用。

      执行以下操作:

      f = open('superlikelist.txt', 'rw') 
      first_line = f.readline()
      #remove one line from file.
      os.system("sed -i -e '1d' " + f)
      

      类似讨论here.

      【讨论】:

      • open 模式应该是'r',而不是'rw'。此外,您需要close 文件(或者,最好使用with 语句)。另外,你真的应该使用subprocess,而不是os.system。真的,没有理由使用sed,因为你可以在 Python 中轻松地做到这一点,除非你故意想让你的代码不能在 Windows 上运行。
      猜你喜欢
      • 2014-10-09
      • 2011-11-17
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      • 2017-09-22
      • 1970-01-01
      相关资源
      最近更新 更多