2016-12-05 6 views
0

私は初心者で、スケジュールされたつぶやきとpython /フラスコの自動リトワーレット用の小さなツイッターツールを書いています。Twitter、複数のプロセス、データベース

バックグラウンドで実行されているプロセスの問題に悩まされました。

スケジュールされたつぶやきとリトウェットが、特定のユーザーのバックグラウンドで同時に動作するようにします。

リトリーブ/スケジュールされたツイートをそれぞれ別々に実行しているこれらのバックグラウンドプロセスを終了したいと考えています。

これを達成するために、以下のコードをどのように変更しますか?

以下のコードを見てもうまくいきますが、スケジュールされたツイートとリトリーを同時に実行することはできません。また、ユーザーがプロセスの1つを終了することを決定した場合、リトワーウェイトとも呼ばれ、他のプロセスも終了します(スケジュールされたツイート)。

私は、特定のプロセスの識別データをデータベースに入れ、クッキーセッションを使用するのではなく、終了する必要があるときにこの識別データをデータベースから呼び出すことを考えましたが、これを実装する方法はわかりませんコード内のアイデア。

import ........ 

mysql = MySQL() 
app = Flask(__name__) 
app.secret_key = 'xxx' 

app.config['MYSQL_DATABASE_USER'] = 'xxx' 
app.config['MYSQL_DATABASE_PASSWORD'] = 'xxx' 
app.config['MYSQL_DATABASE_DB'] = 'xxx' 
app.config['MYSQL_DATABASE_HOST'] = '0.0.0.0' 
mysql.init_app(app) 

@app.route('/showSignin') 
def showSignin(): 
    if session.get('user'): 
     return redirect('/userHome') 
    else: 
     return render_template('signin.html') 

@app.route('/showscheduletweets') 

def showscheduletweets(): 

    if session.get('user'): 
     return render_template('scheduletweets.html') 
    else: 
     return render_template('signin.html') 

    @app.route('/validateLogin',methods=['POST']) 
def validateLogin(): 
    try: 
    _username = request.form['inputEmail'] 
    _password = request.form['inputPassword'] 

    # connect to mysql 

    con = mysql.connect() 
    cursor = con.cursor() 
    cursor.callproc('sp_validateLogin',(_username,)) 
    data = cursor.fetchall() 

    if len(data) > 0: 
     if check_password_hash(str(data[0][3]),_password): 
      session['user'] = data[0][0] 
      consumerkey = data [0][4] 
      consumersecret = data [0][5] 
      accesstoken = data [0][6] 
      tokensecret = data [0][7] 
      twitter = Twython(consumerkey, consumersecret, accesstoken, tokensecret) 
      twitter.update_status(status="xxx says hello.") 
      return render_template('userHome.html') 
     else: 
      return render_template('error.html',error = 'Wrong Email address or Password.') 
    else: 
     return render_template('error.html',error = 'Wrong Email address or Password.') 

except Exception as e: 
    return render_template('error.html',error = str(e)) 
finally: 
    cursor.close() 
    con.close() 

#schedule tweets 

@app.route('/scheduletweets',methods=['POST']) 

def scheduletweets(): 
    if session.get('user'): 
    _username = request.form['inputEmail'] 
    con = mysql.connect() 
    cursor = con.cursor() 
    cursor.callproc('sp_GetTwitter', (_username,)) 
    data = cursor.fetchall() 

    session['user'] = data[0][0] 
    consumerkey = data [0][4] 
    consumersecret = data [0][5] 
    accesstoken = data [0][6] 
    tokensecret = data [0][7] 
    twitter = Twython(consumerkey, consumersecret, accesstoken, tokensecret) 

    tweet1 = request.form['inputTweet1'] 
    tweet2 = request.form['inputTweet2'] 
    tweet3 = request.form['inputTweet3'] 
    tweet4 = request.form['inputTweet4'] 
    tweet5 = request.form['inputTweet5'] 
    tweet6 = request.form['inputTweet6'] 

    Hash1 = request.form['inputHash1'] 
    Hash2 = request.form['inputHash2'] 
    Hash3 = request.form['inputHash3'] 
    Hash4 = request.form['inputHash4'] 

    fruits = [Hash1, Hash2, Hash3, Hash4] 



    list = [tweet1, tweet2, tweet3, tweet4, tweet5, tweet6] 
    def workit(): 

    while True: 
     try: 
      if len(list) > 0: 
       z = random.randint(1, len(fruits)) 
       a = random.sample(fruits, z) 


       b=" ".join(str(x) for x in a) 
       toTweet = list[random.randint(0,len(list))-1] + " " + b 

       twitter.update_status(status=toTweet) 
       time.sleep(10) 


      else: 
       twitter.update_status(status="Oh dear... I'm afraid I'm rather empty =(") 
       break 
     except TwythonError as e: 
      print (e) 


    if 'work_process' not in session: 
    process = Process(target=workit) 
    process.start() 
    pid = process.pid 
    parent_pid = psutil.Process(process.pid).parent().pid 
    session['work_process'] = (parent_pid, pid) 
    return redirect('/showscheduletweets') 
    #retweets 
    @app.route('/retweet',methods=['POST']) 
def retweet(): 
    if session.get('user'): 

    _username = request.form['inputEmail'] 
    con = mysql.connect() 
    cursor = con.cursor() 
    cursor.callproc('sp_GetTwitter', (_username,)) 
    data = cursor.fetchall() 

    session['user'] = data[0][0] 
    consumerkey = data [0][4] 
    consumersecret = data [0][5] 
    accesstoken = data [0][6] 
    tokensecret = data [0][7] 


    Retweet1 = request.form['inputRetweet1'] 
    Retweet2 = request.form['inputRetweet2'] 
    Retweet3 = request.form['inputRetweet3'] 
    Retweet4 = request.form['inputRetweet4'] 
    Exclude1 = request.form['inputExclude1'] 
    Exclude2 = request.form['inputExclude2'] 




    def work(): 
    twitter = Twython(consumerkey, consumersecret, accesstoken, tokensecret) 
    naughty_words = [Exclude1, Exclude2] 
    good_words = [Retweet1, Retweet2, Retweet3, Retweet4] 
    filter = " OR ".join(good_words) 
    blacklist = " -".join(naughty_words) 
    keywords = filter +" -"+ blacklist 
    print(keywords) 
    while True: 
     search_results = twitter.search(q=keywords, count=10) 
     try: 
      for tweet in search_results["statuses"]: 
       try: 
        twitter.retweet(id = tweet["id_str"]) 
        time.sleep(60) 
       except TwythonError as e: 
              print (e) 
     except TwythonError as e: 
            print (e) 

    if 'work_process' not in session: 
    process = Process(target=work) 
    process.start() 
    pid = process.pid 
    parent_pid = psutil.Process(process.pid).parent().pid 
    session['work_process'] = (parent_pid, pid) 
    return redirect('/showretweet') 

     #terminating scheduled tweets and retweets 
     @app.route('/stoptweet', methods=['POST']) 
    def stoptweet(): 
    if 'work_process' in session: 
    parent_pid, pid = session['work_process'] 
    try: 
     process = psutil.Process(pid) 
     if process.parent().pid == parent_pid: 
      process.terminate() 
    except psutil.NoSuchProcess: 
     pass 
    session.pop('work_process') 
    return render_template('index.html') 
else: 
    return render_template('index.html') 

if __name__ == '__main__': 
    app.run(host=os.getenv('IP', '0.0.0.0'),port=int(os.getenv('PORT', xxx))) 

答えて

0

あなたはcelery python moduleを使用すると、背景が働くようスケジュールつぶやきやリツイートを移動することがあります。 http://flask.pocoo.org/docs/0.11/patterns/celery/

あなたはむしろフラスコより、セロリに関連するこれらの機能を飾るします:

さらに情報については、ドキュメントを参照してください。

例として:あなたのスクリプトで

my_schedule_module.py

import my_schedule_module 

、その後:

from celery import Celery, Task 
from celery.result import AsyncResult 

from celery.task.base import periodic_task 

import sqlite3 # Here I use sqlite, can be sql 
import redis # Here I am using redis, you can use another db as well > check documentation 

from datetime import timedelta # used to schedule your background jobs, see in configuration below 


app_schedule = Celery('my_schedule_module') 


''' 
Celery Configuration 
''' 

# a mockup configuration of your background jobs, as example use retweet each 60s 
app_schedule.conf.update(
    CELERY_ACCEPT_CONTENT = ['application/json'], 
    CELERY_TASK_SERIALIZER='json', 
    # CELERY_ACCEPT_CONTENT=['json'], # Ignore other content 
    CELERY_RESULT_SERIALIZER='json', 
    # CELERY_TIMEZONE='Europe/Oslo', 
    # CELERY_ENABLE_UTC=True, 
    CELERYD_TASK_TIME_LIMIT = 600, 
    CELERYD_TASK_SOFT_TIME_LIMIT = 600, 
    CELERYD_MAX_TASKS_PER_CHILD = 1000, 
    CELERYD_OPTS="--time-limit=600 --concurrency=4", 
    BROKER_URL = 'redis://localhost:6379/0', 
    CELERY_RESULT_BACKEND = 'redis://localhost', 
    CELERYBEAT_SCHEDULE = { 
     'add-every-60-seconds': { 
     'task': 'my_schedule_module.retweet', 
     'schedule': timedelta(seconds=60) 
     }, 
    } 
) 

@app_schedule.task() 
def retweet(tweet): 
    # your tweet function 

@app_schedule.task() 
def scheduletweets(): 
    # your background job 
    # pseudo code 
    tweets = get_tweets() 
    process_tweet_list = [] 
    for tweet in tweets: 
      process_tweet_list.append(retweet.s(tweet)) 
    job = group(process_tweet_list) #group is celery.group, see documentation 
    result = job.apply_async() # process job list async 
    print 'result', result.ready(), result.successful() 

ます。また、コールバック関数を使用することができます - 例として、あなたは、日時を更新する場合がありますあなたのつぶやきがretweetedされたときのあなたのデータベースで。この場合

は、あなたは次のような構文を持っているでしょう:

result = my_schedule_module.retweet.apply_async((tweet,) , link=my_schedule_module.callback_to_store_results_of_retweet.s()) 
+0

ことをありがとう、私は前にセロリをしようとしています。私は要求コンテキストに問題が発生しました:RuntimeError:要求コンテキストの外で働いています。 これは、通常、アクティブなHTTP要求を必要とする機能を使用しようとしたことを意味します。 – Lucas

+0

さらに、実際にはどういう意味ですか? " - タイムリミット= 600 --concurrency = 4"、 - = 600、 CELERYD_TASK_SOFT_TIME_LIMIT = 600、= 1000 CELERYD_MAX_TASKS_PER_CHILD、 CELERYD_OPTS = CELERYD_TASK_TIME_LIMITリツイートプロセスが最大600秒続くと、その後に終了することができますということ? – Lucas

+0

リクエストコンテクストに対する私の最初のコメントについて - 予定されているすべてのつぶやきまたはリトライされるべき単語/ハッシュタグがhtmlフォームで入力された後に来る。私はセロリを使用しますが、htmlフォームのコンテキストでセロリを適用する方法はわかりません。 – Lucas

関連する問題