39742


Pythonで検索エンジンを作成したのですがクライアントから任意のURLをpostで送ってクローラーを起動させたいのです。  
フレームワークはflaskを使用しています。

[code]

    ■検索エンジン
    |---■config.py
    |---■manage.py
    |---■web_crawler
    　　|---■\__init__.py
    　　|---■crawler.py
    　　|---■drop_collection.py
    |---■search_engine
    　　|---■\__init__.py
    　　|---■template
    　　　　|---■index.html
    
[/code]

現在はmanage.pyからcrawlerとsearch_engineを動作させています。  
crawlerで最初にwebサイトをクローリングしておいて、その後に検索エンジンを動作させる方法で動いています。

manage.py

[code]

    # -*- coding: utf-8 -*-
    import argparse
    __author__ = 'wataru'
    
    
    if __name__ == '__main__':
        #エラーの時にメッセージを表示する。 
        parser = argparse.ArgumentParser("Runner")
        parser.add_argument('action', type=str, nargs=None, help="Select target 'crawler' or 'webpage'?")
        args = parser.parse_args()
    
        if args.action == 'crawler':
            #コマンドラインでcrawlerって打ち込まれたらweb_crawlerって言うフォルダからcrawler.pyを読み込んでcrawl_webっていうdefを持ってくる    
            from web_crawler.crawler import crawl_web
            crawl_web('http://ltomu.minibird.jp/', 2)
        elif args.action == 'webpage':
            from search_engine import app
            app.run(debug=True, host='0.0.0.0', port=9000)
        elif args.action == 'dropdb':
            from web_crawler.drop_collection import drop_collection
            drop_collection()
        else:
            raise ValueError('Please select "crawler" or "webpage" or "dropdb".')
    
[/code]

現在の構成だとsearch_engineの中にある__init__.pyに検索エンジンのプログラムwebサイトを表示するプログラムが書いてあるのですがこの__init__.pyにcrawler.pyをimportしたいのですがPythonのimportは実行ディレクトリと同様のディレクトリかカレントディレクトリでしかimport出来ないので上の階層はsysを使うと知ったのですがどのように記述したら良いのかわかりません。

以下のコードにsysを追加してcrawler.pyをimportしたい。  
＿init＿.py

[code]

    from urllib.parse import urlparse
    from flask import Flask, render_template, request
    from pymongo import MongoClient
    
    app = Flask(__name__)
    app.config.from_object('config') #flaskのconfigを読み込んでる
    
    # DB settings
    MONGO_URL = app.config['MONGO_URL']
    client = MongoClient(MONGO_URL)
    db = client[urlparse(MONGO_URL).path[1:]]
    col = db["Index"]
    
    
    @app.route('/', methods=['GET', 'POST']) #postはフォームにキーワード
    def index():
        """Return index.html
        """
        if request.method == 'POST':
            keyword = request.form['keyword'] #フォームで入力された文字がkeyword変数に入っているのでそれを持ってくるそこからkeywordに代入
            if keyword:
                if keyword == 'wataru':
                    redirect(url_for('crawler'))
                return render_template(
                    'result.html',
                    query=col.find_one({'keyword': keyword}),
                    keyword=keyword)
        return render_template('index.html')
    
    @app.route('/crawler', methods=['GET', 'POST'])
    def crawlerpage():
        """Return index.html
        """
        if request.method == 'POST':
            url = request.form['url'] 
            if 'http' in url:
                    crawl_web(url, 1) #ここをcrawlerを使うためimportしたい
                    return render_template('done.html')
        return render_template('crawler.html')
    
[/code]

詳しい方お力を貸して頂けると幸いです。


CC BY-SA 3.0
2017-11-21T12:37:09.860
39740
2017-11-24T04:34:16.517
22565
question
python python3 flask
Pythonでプログラムを実行している階層より上のモジュールをimportしたい。


`manage.py`の場所を基準にしますから

単に

[code]

    import web_crawler.crawler
    
[/code]

でよいように見えますが。

* * *

OSなどを気にせずうまく動きそうな書き方だとこんな感じでしょうか。

[code]

    import sys, pathlib
    sys.path.append(str(pathlib.Path(sys.argv[0]).resolve().parents[1]))
    
[/code]

`python -c`や`python -m`で起動した時のことは考えていませんが。


CC BY-SA 3.0
2017-11-21T13:43:38.863
39742
2017-11-21T15:32:50.533
2017-11-21T15:32:50.533
12274
12274
39740
answer


ご質問の内容は実行ディレクトリがsearch_engineである場合に、crawler.pyをimportする方法が相当するかと思います。これにはまず、"検索エンジン"のフォルダをPythonのpathに追加します。

[code]

    import sys
    import os
    # 一つ上のディレクトリを取得
    path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
    sys.path.append(path)
    
[/code]

これで隣のフォルダにあるモジュールimportできるようになるはずです。

[code]

    from web_crawler import crawler
    
[/code]

manage.pyよりも1つ上だった場合、さらにもう一つ親フォルダをさかのぼってpathを追加すればimportできるようになりますが、参照対象が不明確になりやすいので、あまりオススメはできません。


CC BY-SA 3.0
2017-11-24T04:34:16.517
39796
2017-11-24T04:34:16.517
26311
39740
answer