2017-01-18 3 views
1

私はPythonサブプロセスでファイルをアップロードしようとしているDjangoプロジェクト(Django 1.10、Python 3.4.3)に取り組んでいます。私はファイルをアップロードしてアップロードする必要があり、それをやっている間もシステムを使えるようにしたいので、これらのタスクをサブプロセスに置くと思った。ファイルをPythonサブプロセスでアップロードする

今、ファイルをアップロードするだけです。

最初の試み:

アプリ/ビュー/ UploadView.py

class NewUploadView(TemplateView): 
    template_name = "../templates/simulation/upload.html" 

    @transaction.atomic 
    def post(self, request): 
     if request.method == 'POST': 
      if not request.FILES['input_file']: 
       return HttpResponseBadRequest("No 'input_file' is provided") 
      else: 
       sim_name = self.request.POST.get(u"name", None) 

       p = Popen(["/.virtualenvs/env/bin/python3.4", "manage.py", 
        "load_simulation", str(request.FILES['input_file'], 
        str(sim_name)]) 

       p.communicate() 

       # Redirect to appropriate page 
       HttpResponseRedirect(reverse('home.display_simulations'))` 

アプリ/管理/コマンド/ load_simulation.py

import csv 
import os 

from django.conf import settings 
from django.core.management.base import BaseCommand 

from website.apps.home.models import Simulation, Location, Data, SimulationModel 


class Command(BaseCommand): 
    help = 'Upload csv data file and save objects in database' 

    def add_arguments(self, parser): 
     parser.add_argument("my_file", type=str) 
     parser.add_argument("simulation_name", type=str) 

    def handle(self, *args, **options): 
     """ 
     Upload data file 
     :param args: 
     :param options: 
     :return: 
     """ 
     my_file = options["my_file"] 
     simulation_name = options["simulation_name"] 

     # Save the simulation object, with the data_file 
     simulation = Simulation.objects.create(name=simulation_name, data_file=my_file) 
     simulation.save() 

     filename = os.path.join(settings.MEDIA_ROOT, "simulation_files", simulation.getfilename()) 
     file_obj = open(filename, 'r') 
     dictreader = csv.DictReader(file_obj) 
     line = None 

     for line in dictreader: 
      location = Location.objects.filter(
       department_code=line['department_code'], 
       municipality_code=line['municipality_code'], 
      ).first() 

      if not location: 
       location = Location.objects.create(
        department=line['department'], 
        department_code=line['department_code'], 
        municipality=line['municipality'], 
        municipality_code=line['municipality_code'], 
       ) 

      Data.objects.create(
       location=location, 
       date=line['date'].split(" ")[0], # Assuming date is in "YYYY-MM-DD HH:MM:SS" format 
       simulation=simulation, 
       value_low=line['value_low'], 
       value_mid=line['value_mid'], 
       value_high=line['value_high'], 
      ) 

     simulation.is_uploaded = True 
     simulation.save() 
     print("DONE WITH LOAD SIMULATION!") 

私はそれを持っていますファイルがに保存されるように設定しますディレクトリ。しかし、ファイルはサーバーに保存されません。つまり、ファイルがその場所にないため、ファイルを開こうとする行のload_simulation.pyファイルでエラーが発生します。

次に、TemporaryFileを文字列として渡していることに気付きました。おそらくそれが問題の一部です。

二回目

私は標準入力としてファイルに取るようにUploadView.pyの一部を変更しました。

 p = Popen(["/.virtualenvs/env/bin/python3.4", "manage.py", 
           "load_simulation", str(sim_name), is_historical], 
           stdin=PIPE) 

     p.communicate(input=request.FILES['output_file']) 

と、次のようにload_simulation.pyを開始するように修正:私は、次の質問/答えからもらった

class Command(BaseCommand): 
    help = 'Upload csv data file and save objects in database' 

    def add_arguments(self, parser): 
     parser.add_argument("my_file", type=str) 
     parser.add_argument("simulation_name", type=str) 

    def handle(self, *args, **options): 
     """ 
     Upload data file 
     :param args: 
     :param options: 
     :return: 
     """ 

     simulation_name = options["simulation_name"] 

     my_file = input() 

     # Save the simulation object, with the data_file 
     simulation = Simulation.objects.create(name=simulation_name, data_file=my_file.name) 
     simulation.save() 

     filename = os.path.join(settings.MEDIA_ROOT, "simulation_files", simulation.getfilename()) 
     file_obj = open(filename, 'r') 
     dictreader = csv.DictReader(file_obj) 

     ... same as before ...  

Python3 subprocess communicate example

これは私にエラーを与える

TypeError: 'InMemoryUploadedFile' does not support the buffer interface

私はサブプロセスを扱うのが初めてで、次に試してみるべきものを失っています。私はp.communicate()がここでは最善の選択ではないかもしれないことに気づきますが、基本的な機能をダウンさせてから改善することができたらと思っています。提案やアドバイスが大歓迎です!

答えて

0

申し訳ありませんが、私はサブプロセスでファイルをアップロードするという基本的な問題を解決しました。 Simulationオブジェクトが作成されると、ファイルは/media/simulation_filesに保存されます。なんらかの理由で、Simulationがサブプロセスに保存されていると、これは機能しません。そのため、サブプロセスを作成する前に、ビューに移動してオブジェクトを保存しました。

次に、Popenは、シミュレーション全体(データファイルを含む)にアクセスするために、新しく作成されたSimulationのIDのみを引数として必要とします。

重要

私はビューで作成Simulationオブジェクトがサブプロセスにアクセスできなくなり、それ以外の場合は@transaction.atomicデコレータを削除する必要がありました。

TL; DRバージョン:

UploadView.py

class NewerUploadView(TemplateView): 
    template_name = "../templates/simulation/upload.html" 

    def post(self, request): 
     if request.method == 'POST': 
      if not request.FILES['output_file']: 
       return HttpResponseBadRequest("No 'output_file' is provided") 
      else: 
       sim_name = self.request.POST.get(u"name", None) 

       # Create the Simulation here to save the file 
       simulation = Simulation.objects.create(name=simulation_name, 
                 data_file=fp) 
       simulation.save() 

       # Get the new Simulation object 
       new_sim = Simulation.objects.get(id=sim_id) 

       p = Popen(["/.virtualenvs/env/bin/python3.4", "manage.py", 
        "load_simulation", str(new_sim.id)], stdout=PIPE, stderr=PIPE) 
       p.communicate() 

       # Redirect to appropriate page 
       return HttpResponseRedirect(reverse('home.display_simulations')) 

load_simulation.py

class Command(BaseCommand): 
    help = 'Upload csv data file and save objects in database' 

    def add_arguments(self, parser): 
     parser.add_argument("sim_id", type=int) 

    def handle(self, *args, **options): 
     """ 
     Upload data file 
     :param args: 
     :param options: 
     :return: 
     """ 

     sim_id = options["sim_id"] 
     sim = Simulation.objects.get(id=sim_id) 
     filename = os.path.join(settings.MEDIA_ROOT, sim.data_file.name) 
     file_obj = open(filename, 'r') 
     dictreader = csv.DictReader(file_obj) 
     line = None 

     for line in dictreader: 

      location = Location.objects.filter(
       department_code=line['department_code'], 
       municipality_code=line['municipality_code'], 
      ).first() 

      if not location: 
       location = Location.objects.create(
        department=line['department'], 
        department_code=line['department_code'], 
        municipality=line['municipality'], 
        municipality_code=line['municipality_code'], 
       ) 

      Data.objects.create(
       location=location, 
       date=line['date'].split(" ")[0], # Assuming "YYYY-MM-DD HH:MM:SS" 
       simulation=sim, 
       value_low=line['value_low'], 
       value_mid=line['value_mid'], 
       value_high=line['value_high'], 
      ) 
     sim.is_uploaded = True 
     sim.save() 
     print("DONE WITH LOAD SIMULATION!") 
関連する問題