Ошибка AttributeError в Python при запуске на веб-сервере

Вопрос или проблема

У меня есть код, который работает довольно хорошо из командной строки, но при запуске через веб-сервер Apache с использованием PHP и подпроцесса Racket я получаю эту ошибку в логах сервера:

(Traceback (most recent call last):   File "/opt/homebrew/var/www/drive/cut_1D.py", line 59, in <module>     from_VTK = fb.from_VTK(data_path)                ^^^^^^^^^^^ AttributeError: module 'fibo' has no attribute 'from_VTK')

Исходный код Python cut_1D.py выглядит так:


# перед запуском установите: export PYTHONPATH=.:fibo
# python3.11 cut_1D.py data ./BepiColombo-Mio_MSO-orbit_1min_short.txt output
# добавлено Дамиеном Матеем

import numpy as np
import matplotlib.pyplot as plt
import fibo as fb
import sys

#from scipy.ndimage.filters import gaussian_filter as gf
# выше устарело и будет удалено
from scipy.ndimage import gaussian_filter as gf

from scipy.interpolate import RegularGridInterpolator

######################################################################
# Здесь вы задаете жестко закодированные входные параметры:
#  -) tars = список полей/скаляров, которые будут обрезаны вдоль траектории
#  -) cycle_min, cycle_max = пределы симуляционного цикла для резки
#  -) word = строка символов для именования выходного файла
######################################################################
tars = ['B','rhoe0']
cycle_min = 5000
cycle_max  = 8000
word = 'Mio'

#######################################################################
# Здесь вы определяете пути к 3 файлам с помощью sys
#######################################################################
data_path = sys.argv[1] # здесь вы указываете путь для запуска
traj_file = sys.argv[2] # здесь вы указываете траекторию в координатах MSO
save_path = sys.argv[3] # здесь вы указываете путь для сохранения извлеченной траектории

#######################################################################
# Здесь вы определяете две рутинные функции для изменения координат 
# MSO означает солнечную орбиту, центрированную на Меркурии, т.е. это система отсчета для определения 
# траектории космического аппарата
#######################################################################
def coordinate_box_to_MSO(x,y,z):
    x_mso = -(x - xc)/R
    y_mso = -(y - yc)/R
    z_mso =  (z - zc)/R
    return x_mso, y_mso, z_mso
def coordinate_MSO_to_box(x,y,z):
    x_box = -(x*R - xc)
    y_box = -(y*R - yc)
    z_box =  (z*R + zc)
    return x_box, y_box, z_box

#######################################################################
# Здесь вы загружаете параметры симуляции из файла SimulationData.txt
# с использованием рутины в fibo/mod_from.py
#######################################################################
print()
print('Загрузка параметров симуляции (SimulationData.txt)')
print()

from_VTK = fb.from_VTK(data_path)
from_VTK.get_meta(silent=False)
x = np.linspace(0,from_VTK.meta['xl'],from_VTK.meta['nx'])
y = np.linspace(0,from_VTK.meta['yl'],from_VTK.meta['ny'])
z = np.linspace(0,from_VTK.meta['zl'],from_VTK.meta['nz'])
nx,ny,nz = from_VTK.meta['nnn']
xc = from_VTK.meta['xc']
yc = from_VTK.meta['yc']
zc = from_VTK.meta['zc']+from_VTK.meta['Doff']
R = from_VTK.meta['R']

#######################################################################
# Здесь вы открываете .txt с траекторией космического аппарата и вычисляете некоторые данные
#######################################################################
print()
print('Открытие .txt с траекторией космического аппарата и вычисление некоторых данных')
print()

tt, xx, yy, zz = np.loadtxt(traj_file,unpack=True)
d = np.sqrt(xx**2+yy**2+zz**2)
i_CA = np.where(d==min(d))
tt = (tt-tt[i_CA])
Vx_array = []
Vy_array = []
Vz_array = []
xx1_box, yy1_box, zz1_box = coordinate_MSO_to_box(xx,yy,zz) # должен быть траекторией космического аппарата

#######################################################################
# Здесь вы перебираете время симуляций и tars для загрузки
# данных симуляции (3D кубов на данных, записанных в vtk), это 
# выполняется с использованием процедур get_vect и get_scal в fibo/mod_from.py
#######################################################################

print()
print('цикл по временным точкам симуляций и по tars')
print()

print('from_VTK.meta[\'segcycles\']=',from_VTK.meta['segcycles'])
print()

for seg in from_VTK.meta['segcycles']:
    print()
    print('seg=',seg)
    print()
    if cycle_min<=seg<=cycle_max :
        print('ЗАГРУЗКА->',seg)
        for tar in tars:

            print()
            print('tar=",tar)
            print()

            # открытие txt файла для вывода
            file_out = open(save_path+"/trajectory-near_'+word+'_'+tar+'_'+str(seg)+'.txt','w')
            file_out.write('#index\t X_MSO\t Y_MSO\t Z_MSO\t Vx\t Vy\t Vz\n')

            # проверка, является ли tar скалярным (немного жестко закодировано, может быть изменено)
            if (('rho' in tar) or ('T' in tar)):
                scalar=True
            else:
                scalar=False

            # загрузка данных с использованием fibo/mod_from.py
            # и интерполяция на сетку box
            if (scalar==False):
                Vect = from_VTK.get_vect(from_VTK.meta['name']+'_'+tar+'_'+str(seg),seg,fibo_obj=None,tar_var=tar,silent=True)
                fx  = RegularGridInterpolator((x,y,z), Vect[0])
                fy  = RegularGridInterpolator((x,y,z), Vect[1])
                fz  = RegularGridInterpolator((x,y,z), Vect[2])
            elif (scalar==True):
                Vect = from_VTK.get_scal(from_VTK.meta['name']+'_'+tar+'_'+str(seg),seg,fibo_obj=None,tar_var=tar,silent=True)
                fx = RegularGridInterpolator((x,y,z), Vect)

            # цикл по точкам траектории
            for ii in range(0,len(xx)):

                # print()
                # print('ii=',ii)
                # print()

                # если точка траектории находится внутри коробки
                if((xx1_box[ii]>0)*(yy1_box[ii]>0)*(zz1_box[ii]>0)*(xx1_box[ii]<max(x))*(yy1_box[ii]<max(y))*(zz1_box[ii]<max(z))):

                    # интерполяция поля до точки траектории
                    point = np.array([[xx1_box[ii],yy1_box[ii],zz1_box[ii]],[0,0,0]])
                    Vx_array.append(fx(point)[0])
                    if (scalar==False):
                        Vy_array.append(fy(point)[0])
                        Vz_array.append(fz(point)[0])
                    elif (scalar==True):
                        Vy_array.append(np.nan)
                        Vz_array.append(np.nan)

                # иначе точка вне коробки
                else:
                    Vx_array.append(np.nan)
                    Vy_array.append(np.nan)
                    Vz_array.append(np.nan)

                # запись в выходной файл
                file_out.write('%f\t%f\t%f\t%f\t%f\t%f\t%f\n'%(tt[ii],xx[ii],yy[ii],zz[ii],-Vx_array[ii],-Vy_array[ii],Vz_array[ii]))

            # закрытие txt выходного файла
            file_out.close()

Проблема в строке 59, но в командной строке код работал идеально, я предполагаю, что какая-то переменная окружения отсутствует…

Модуль под названием python source code находится в поддиректории fibo init.py:


#! /bin/env python
# coding: utf8

#---------------------------------------------------------------------------------------
#-(1)-----21.12.18----FDP:S,F-----------------------------------------------------------
#-(2)-----30.12.18----FDP:S,J,R---------------------------------------------------------
#-(3)-----02.04.19----FDP:S,P,L---------------------------------------------------------
#-(4)-----04.04.19----FDP:S,J,L---------------------------------------------------------
#---------------------------------------------------------------------------------------
#-(alpha)-19.07.19----FDP:S,J,L---------------------------------------------------------
#-(beta0)-12.11.19----FDP:S,F-----------------------------------------------------------
#-(beta1)-19.11.19----FDP:S-------------------------------------------------------------
#-(beta2)-25.11.19----FDP:S,L-----------------------------------------------------------
#-(beta3)-21.03.20----FDP:S-------------------------------------------------------------
#-(gamma)-03.06.21----FDP:S,J-----------------------------------------------------------
#---------------------------------------------------------------------------------------

from mod_from import  from_VTK
from mod_phybo import phybo

import mod_get
import mod_axis
import mod_extract
import mod_calc
import mod_find
import mod_comp
import mod_draw
import mod_print
import mod_extra

class fibo (mod_get.fibo_get,
            mod_axis.fibo_axis,
            mod_extract.fibo_extract,
            mod_calc.fibo_calc,
            mod_find.fibo_find,
            mod_comp.fibo_comp,
            mod_draw.fibo_draw,
            mod_print.fibo_print,
            mod_extra.fibo_extra):
  """
  fibo — это объект python, созданный для хранения ваших данных симуляции и выполнения простых операций с ними автоматически 
  все функции предназначены для массивов данных формы [nx,ny,nz] (никаких других индексов, пожалуйста - это сделано для облегчения рутин и избавления от циклов)

  [fibo.data] означает [str] в данных или [np.ndarray(nx,ny,nz)]
  """

  def __init__(self,
      fibo_name):    #имя набора данных, с которым вы работаете (часть симуляции)

    self.fibo_name = str(fibo_name)

    self.data = {}  #словарь np.ndarray(nx,ny,nz)
    self.pnts = {}  #словарь np.ndarray(3,points)

    self.meta = {}  #словарь метаданных - должен быть скопирован из загрузчиков
    self.stat = {}  #словарь статистических значений 

  #------------------------------------------------------------
  def help(self):

    print("Что это за бардак?")

    print('pippo = fb.fibo("pippo")')
    print('dir(fb)')
    print('dir(fb.fibo)')
    print('pippo.data.keys() --> список доступных данных')
    print('pippo.data["newname"] = pippo.data.pop("oldname")')
    print('np.unravel_index(np.argmax(...),np.shape(...))')

mod_from.py содержит from_VTK :



#! /bin/env python

import collections 
import codecs

import numpy as np
import os
import pickle
import matplotlib as mpl
import matplotlib.pyplot as plt
import scipy.ndimage as ndm
import itertools as itt
import struct
import re
import time
import vtk
from vtk.util import numpy_support as VN
from vtk.numpy_interface import dataset_adapter as dsa
from vtk.numpy_interface import algorithms as algs
import xml.etree.ElementTree as ET

#---------------------------------------------------------------------------------------
#------заполнение-объектов-fibo-из-различных-источников---------------------------------
#-------или-просто-возьмите-ваши-данные--------------------------------------------
#---------------------------------------------------------------------------------------

#---------------------------------------------------------------------------------------
class from_VTK (object):

  def __init__(self, 
      address):
    """ 
    Создает объект для извлечения данных из файлов VTK

    Параметры :
      - address      [address] где находятся ваши данные (папка с сегментами внутри)

    """
    self.address = address
    self.meta = {}

  #------------------------------------------------------------
  def get_meta(self,  #считает строки в файле и вызывает соответствующую функцию для получения метаданных
      extra_address="",
      silent = True):
    """
    ------------------------------------------------------------------------------------
      заполняет список метаданных 
    ------------------------------------------------------------------------------------
    extra_address=""      [address] для доступа к любой подпапке, где находятся ваши метаданные
    silent        = True    [bool] вы хотите видеть всю информацию, напечатанную на экране?
    ------------------------------------------------------------------------------------
    """

    with open(os.path.join(self.address,extra_address,'SimulationData.txt'),'r') as foo:
      line_number = len(foo.readlines())

    if line_number==35 : old_vers=True
    elif line_number>35 : old_vers=False

    self.get_meta_A(old_vers,extra_address)

    #---------получить-размеры-вашей-симуляции----------

    self.meta['dx'] = self.meta['xl']/self.meta['nx']
    self.meta['dy'] = self.meta['yl']/self.meta['ny']
    self.meta['dz'] = self.meta['zl']/self.meta['nz']

    self.meta['nnn'] = (self.meta['nx'], self.meta['ny'], self.meta['nz'])
    self.meta['lll'] = (self.meta['xl'], self.meta['yl'], self.meta['zl'])
    self.meta['ddd'] = (self.meta['dx'], self.meta['dy'], self.meta['dz']) 

    self.meta['ppp'] = (False, False, False)       # ЖЕСТКО ЗАКОДИРОВАНО !!! 

    self.meta['x'] = np.arange(0.,self.meta['xl'],self.meta['dx'])
    try:
        self.meta['y'] = np.arange(0.,self.meta['yl'],self.meta['dy'])
    except:
        self.meta['y'] = np.array([0.])
    try:
        self.meta['z'] = np.arange(0.,self.meta['zl'],self.meta['dz'])
    except:
        self.meta['z'] = np.array([0.])

    #----------получить-время-информацию-из-всех-vtk-файлов----------------- 

    segments = [f for f in os.listdir(self.address) if f.split('.')[-1]=='vtk']
    for i in range(len(segments)):
        if i == 0:
          self.meta['name'] = segments[i].split('_')[0]
        segments[i] = segments[i].split('_')[-1].split('.')[0]
    segments = set(segments)
    segments = map(str, sorted(map(int, segments)))
    self.meta['segcycles']=[]
    self.meta['segtimes']=[]
    for seg in segments:
      self.meta['segcycles'].append(int(seg))
      self.meta['segtimes'].append(float(seg)*self.meta['dt'])

    #----------добавить-информацию-о-специях-----------------

    species  = []
    for isp in range(0,self.meta['nss']):
      if self.meta['sQOM'][isp]<0  : species.append('e'+str(isp))
      elif self.meta['sQOM'][isp]>0  : species.append('i'+str(isp))

    self.meta['species']  = species

    if self.meta['ny'] == 1:
      self.meta['space_dim'] = '1D'
    elif self.meta['nz'] == 1:
      self.meta['space_dim'] = '2D'
    else:
      self.meta['space_dim'] = '3D'

    #----------печать-резюме-----------------

    if not silent : 
      print('iPIC3D> число ячеек               :  ', self.meta['nnn'])
      print('iPIC3D> размер области               :  ', self.meta['lll'])
      print('iPIC3D> интервал сетки              :  ', self.meta['ddd'])
      print('iPIC3D> периодичность               :  ', self.meta['ppp'])
      print('iPIC3D> шаг времени                 :  ', self.meta['dt'])
      print('iPIC3D> специи                   :  ', self.meta['species'])
      for i in range(self.meta['nss']):
        print('          '+species[i]+' заряд-на-массу           :  ', self.meta['sQOM'][i])

  #------------------------------------------------------------
  def get_meta_A(self,
      old_vers=False,
      extra_address=""):
    """
    ------------------------------------------------------------------------------------
      дополнительная рутина, читает метаданные из SimulationData.txt
    ------------------------------------------------------------------------------------
      old_vers      = False   [bool] ваша симуляция старше 11/2021? значит, что я изменил simulationdata.txt в ipic3d
      extra_address=""      [address] для доступа к любой подпапке, где находятся ваши метаданные
    ------------------------------------------------------------------------------------
    """

    #получить информацию о сетке из SimulationData.txt
    infos = open(os.path.join(self.address,extra_address,'SimulationData.txt'),'r')

    infos.readline() #---------------------------
    infos.readline() #-  Параметры Симуляции  -
    infos.readline() #---------------------------
    self.meta['nss'] = int(infos.readline().split('=')[-1]) #количество видов
    stag=[]
    sQOM=[]
    for i in range(self.meta['nss']):
      sQOM.append(float(infos.readline().split('=')[-1]))
    self.meta['sQOM'] = sQOM
    infos.readline() #---------------------------
    self.meta['xl'] = float(infos.readline().split('=')[-1]) #физические размеры коробки
    self.meta['yl'] = float(infos.readline().split('=')[-1])
    self.meta['zl'] = float(infos.readline().split('=')[-1])
    self.meta['nx'] = int(infos.readline().split('=')[-1]) #размеры сетки коробки
    self.meta['ny'] = int(infos.readline().split('=')[-1])
    self.meta['nz'] = int(infos.readline().split('=')[-1])
    if not old_vers :
      infos.readline() #---------------------------
      self.meta['XLEN'] = int(infos.readline().split('=')[-1]) # сетка mpi
      self.meta['YLEN'] = int(infos.readline().split('=')[-1])
      self.meta['ZLEN'] = int(infos.readline().split('=')[-1])
      infos.readline() #---------------------------
      self.meta['xc'] = float(infos.readline().split('=')[-1]) #позиция планеты
      self.meta['yc'] = float(infos.readline().split('=')[-1])
      self.meta['zc'] = float(infos.readline().split('=')[-1])
      self.meta['R'] = float(infos.readline().split('=')[-1]) #радиус планеты
      self.meta['Doff'] = float(infos.readline().split('=')[-1])
      infos.readline() #---------------------------
      self.meta['SAL'] = int(infos.readline().split('=')[-1])
      self.meta['Nsal'] = int(infos.readline().split('=')[-1])
    infos.readline() #---------------------------
    self.meta['dt'] = float(infos.readline().split('=')[-1]) #шаг времени
    self.meta['nsteps'] = int(infos.readline().split('=')[-1]) #количество шагов
    infos.readline() #---------------------------
    for i in range(self.meta['nss']):
      infos.readline() #rho init species
      infos.readline() #rho inject species
    infos.readline() #толщина текущего слоя
    self.meta['Bx0'] = float(infos.readline().split('=')[-1]) #Bx0
    self.meta['By0'] = float(infos.readline().split('=')[-1]) #By0
    self.meta['Bz0'] = float(infos.readline().split('=')[-1]) #Bz0
    if not old_vers :
      infos.readline() #---------------------------
      self.meta['Vx0'] = float(infos.readline().split('=')[-1]) #Vx0
      self.meta['Vy0'] = float(infos.readline().split('=')[-1]) #Vy0
      self.meta['Vz0'] = float(infos.readline().split('=')[-1]) #Vz0
      self.meta['vths'] = []
      for i in range(self.meta['nss']):
        self.meta['vths'].append(float(infos.readline().split('=')[-1])) #vth species
    infos.readline() #---------------------------
    infos.readline() #Сглаживание
    infos.readline() #2D сглаживание
    infos.readline() #nvolte ?
    infos.readline() #GMRES допустимая ошибка
    infos.readline() #CG допустимая ошибка
    infos.readline() # Допустимая ошибка Передвижения

    infos.readline() #---------------------------
    infos.readline() #Результаты сохранены в:
    infos.readline() #Перезапуск сохранен в:

    infos.readline() #---------------------------
    infos.close()

    # внимание, существует несколько версий этой функции!!!
  #------------------------------------------------------------
  def get_scal(self,
      tar_file,
      seg,
      fibo_obj = None,  
      tar_var = None,  
      double_y = False,
      silent = True):
    """ 
    Читает скаляр из .vtk файла

    Параметры :
      - tar_file           [str] целевой файл для чтения (не включайте '.vtk')
      - seg                [str] цикл симуляции
      - fibo_obj = None    [None или fibо] объект fibo, который вы хотите заполнить, иначе возвращает значения 
      - tar_var = None     [None или str] имя, переменной, которой будет дано
      - double_y = False   [bool] был ли ваш файл распечатан дважды в y?
      - silent = True      [bool] печатать статус в конце?
    Возвращает :
      - scal               [fibo_var] 

    """  

    #создайте вектор данных, заполните его!
    data_file = open(os.path.join(self.address,tar_file+'.vtk'),'r', errors="replace")

    if tar_var == None : 
      tar_var = data_file.readline().split()[0]+'%.8i'%int(seg)
    else : 
      tar_var = tar_var+'%.8i'%int(seg)
      data_file.readline()

    data_file.readline()
    data_format = data_file.readline()
    data_structure = data_file.readline().split()[1]
    self.meta['nx'], self.meta['ny'], self.meta['nz'] = map(int, data_file.readline().split()[1:4])
    data_file.readline()
    self.meta['dx'], self.meta['dy'], self.meta['dz'] = map(float, data_file.readline().split()[1:4])
    data_file.readline()
    data_file.readline()  #NB здесь вы видите произведение nx*ny*nz
    data_file.readline()
    data_file.readline()

    data_file.close()

    if double_y : self.meta['ny'] = self.meta['ny']/2 #NB здесь вы делите коробку на два по y!

    if data_structure == 'STRUCTURED_POINTS': reader = vtk.vtkStructuredPointsReader() #здесь вы можете добавить другие читатели, если это необходимо

    t0 = time.time()
    reader.SetFileName(os.path.join(self.address,tar_file+'.vtk'))
    t1 = time.time()
    print('DEBUG: SetFileName',t1-t0)
    reader.ReadAllScalarsOn()
    t2 = time.time()
    print('DEBUG: ReadAllVectors',t2-t1)
    reader.Update()
    t3 = time.time()
    print('DEBUG: Update',t3-t2)
    vtk_output = reader.GetOutput()
    t4 = time.time()
    print('DEBUG: GetOutput',t4-t3)

    if vtk_output.GetDimensions()[0] != self.meta['nx'] : print('ERROR: неверное количество ячеек вдоль x (Nx)')
    if vtk_output.GetDimensions()[2] != self.meta['nz'] : print('ERROR: неверное количество ячеек вдоль z (Nz)')
    if not double_y and vtk_output.GetDimensions()[1] != self.meta['ny'] :  print('ERROR: неверное количество ячеек вдоль y (Ny) ; double_y=False')
    if double_y and vtk_output.GetDimensions()[1] != self.meta['ny']*2 :    print('ERROR: неверное количество ячеек вдоль y (Ny) ; double_y=True')

    scal = VN.vtk_to_numpy(vtk_output.GetPointData().GetScalars())
    t5 = time.time()
    print('DEBUG: vtk_to_numpy',t5-t4)
    print('reader=",reader)
    print("vtk_output=",vtk_output)
    print("vect=",scal)

    if double_y :     scal = scal.reshape(self.meta["nz"],2*self.meta['ny'],self.meta['nx']).transpose(2,1,0) #пересчитать плоский массив в 3D массив
    else :            scal = scal.reshape(self.meta['nz'],self.meta['ny'],self.meta['nx']) .transpose(2,1,0)

    if double_y : scal = scal[:,:self.meta['ny'],:]

    if (fibo_obj != None) :
      fibo_obj.data[tar_var] = scal
    else: 
      return scal

    if not silent:
      print('get_scal_from_VTK> формат данных             :  ', data_format)
      print('get_scal_from_VTK> структура данных          :  ', data_structure)
      print('get_scal_from_VTK> размеры сетки         :  ', self.meta['nnn'])
      print('get_scal_from_VTK> размер сетки               :  ', self.meta['lll'])
      print('get_scal_from_VTK> шаг сетки            :  ', self.meta['ddd'])
      if (fibo_obj != None) :
        print('get_scal_from_VTK> создан fibo_obj.data['+tar_var+']')

  #------------------------------------------------------------
  def get_vect(self,
      tar_file,
      seg,
      fibo_obj = None,
      tar_var = None,
      double_y = False,
      silent=True):
    """ 
    Читает вектор из .vtk файла

    Параметры :
      - tar_file           [str] целевой файл для чтения (не включайте '.vtk')
      - fibo_obj = None    [None или fibо] объект fibo, который вы хотите заполнить, иначе возвращает значения 
      - tar_var = None     [None или str] имя, переменной, которой будет дано
      - double_y = False   [bool] был ли ваш файл распечатан дважды в y?

    Возвращает :
      - scal               [fibo_var] 

    """

    #создайте вектор данных, заполните его!
    data_file = open(os.path.join(self.address,tar_file+'.vtk'),'r',errors="replace") # b , бинарный но ошибка после

    print("DEBUG: mod_probe : tar_file =",tar_file); # добавлено Дамиеном Матеем

    if tar_var == None : 
      tar_var_x,tar_var_y,tar_var_z = data_file.readline().split()[0][1:-1].split(',')
      tar_var_x = tar_var_x+'%.8i'%int(seg)
      tar_var_y = tar_var_y+'%.8i'%int(seg)
      tar_var_z = tar_var_z+'%.8i'%int(seg)
    else : 
      tar_var_x = tar_var+'_x'+'%.8i'%int(seg)
      tar_var_y = tar_var+'_y'+'%.8i'%int(seg)
      tar_var_z = tar_var+'_z'+'%.8i'%int(seg)
      data_file.readline()

    data_file.readline()
    data_format = data_file.readline()
    data_structure = data_file.readline().split()[1]
    self.meta['nx'], self.meta['ny'], self.meta['nz'] = map(int, data_file.readline().split()[1:4])
    data_file.readline() # здесь ORIGIN
    self.meta['dx'], self.meta['dy'], self.meta['dz'] = map(float, data_file.readline().split()[1:4])
    data_file.readline()
    data_file.readline()  #NB здесь вы видите произведение nx*ny*nz
    data_file.readline()

    data_file.close()

    if double_y : self.meta['ny'] = self.meta['ny']/2  #NB здесь вы делите коробку на два по y!

    if data_structure == 'STRUCTURED_POINTS': reader = vtk.vtkStructuredPointsReader() #здесь вы можете добавить другие читатели, если это необходимо

    t0 = time.time()
    reader.SetFileName(os.path.join(self.address,tar_file+'.vtk'))
    t1 = time.time()
    print('DEBUG: SetFileName',t1-t0)
    reader.ReadAllVectorsOn()
    t2 = time.time()
    print('DEBUG: ReadAllVectors',t2-t1)
    reader.Update()
    t3 = time.time()
    print('DEBUG: Update',t3-t2)
    vtk_output = reader.GetOutput()
    t4 = time.time()
    print('DEBUG: GetOutput',t4-t3)

    if vtk_output.GetDimensions()[0] != self.meta['nx'] : print('ERROR: неверное количество ячеек вдоль x (Nx)')
    if vtk_output.GetDimensions()[2] != self.meta['nz'] : print('ERROR: неверное количество ячеек вдоль z (Nz)')
    if not double_y and vtk_output.GetDimensions()[1] != self.meta['ny'] :  print('ERROR: неверное количество ячеек вдоль y (Ny) ; double_y=False')
    if double_y and vtk_output.GetDimensions()[1] != self.meta['ny']*2 :    print('ERROR: неверное количество ячеек вдоль y (Ny) ; double_y=True')

    vect = VN.vtk_to_numpy(vtk_output.GetPointData().GetArray(tar_var))
    t5 = time.time()
    print('DEBUG: vtk_to_numpy',t5-t4)
    print('reader=",reader)
    print("vtk_output=",vtk_output)
    print("vect=",vect)

    if double_y :
      vect_x = vect[:,0].reshape(self.meta["nz"],self.meta['ny']*2,self.meta['nx']).transpose(2,1,0)
      vect_y = vect[:,1].reshape(self.meta['nz'],self.meta['ny']*2,self.meta['nx']).transpose(2,1,0)
      vect_z = vect[:,2].reshape(self.meta['nz'],self.meta['ny']*2,self.meta['nx']).transpose(2,1,0)
    else :
      vect_x = vect[:,0].reshape(self.meta['nz'],self.meta['ny'],self.meta['nx']).transpose(2,1,0)
      vect_y = vect[:,1].reshape(self.meta['nz'],self.meta['ny'],self.meta['nx']).transpose(2,1,0)
      vect_z = vect[:,2].reshape(self.meta['nz'],self.meta['ny'],self.meta['nx']).transpose(2,1,0)

    if double_y : 
      vect_x = vect_x[:,:self.meta['ny'],:]
      vect_y = vect_y[:,:self.meta['ny'],:]
      vect_z = vect_z[:,:self.meta['ny'],:]

    if (fibo_obj != None) :
      fibo_obj.data[tar_var_x] = vect_x
      fibo_obj.data[tar_var_y] = vect_y
      fibo_obj.data[tar_var_z] = vect_z
    else: return np.array([vect_x, vect_y, vect_z])

    if not silent:
      print('get_vect_from_VTK> формат данных             :  ', data_format)
      print('get_vect_from_VTK> структура данных          :  ', data_structure)
      print('get_vect_from_VTK> размеры сетки         :  ', self.meta['nnn'])
      print('get_vect_from_VTK> размер сетки               :  ', self.meta['lll'])
      print('get_vect_from_VTK> шаг сетки            :  ', self.meta['ddd'])
      if (fibo_obj != None) :
        print('get_vect_from_VTK> создан fibo_obj.data['+tar_var_x+']') 
        print('get_vect_from_VTK> создан fibo_obj.data['+tar_var_y+']') 
        print('get_vect_from_VTK> создан fibo_obj.data['+tar_var_z+']') 

#---------------------------------------------------------------------------------------
class from_HDF5 (object):

  def __init__(self, 
      address):
    """ 
    Создает объект для извлечения данных из файлов HDF5

    Параметры :
      - address      [address] где находятся ваши данные (папка с сегментами внутри)

    """
    self.address = address
    self.meta = {}

  #------------------------------------------------------------
  def get_scal(self,
      tar_file,
      seg,
      path,
      fibo_obj = None,  
      tar_var = None,  
      double_y = False,
      silent = True):
    """ 
    Читает скаляр из .h5 файла

    Параметры :
      - tar_file           [str] целевой файл для чтения (не включайте '.h5')
      - seg                [str] цикл симуляции
      - path               [str] путь к полю внутри словаря hdf5               
      - fibo_obj = None    [None или fibо] объект fibo, который вы хотите заполнить, иначе возвращает значения 
      - tar_var = None     [None или str] имя, переменной, которой будет дано
      - double_y = False   [bool] был ли ваш файл распечатан дважды в y?
      - silent = True      [bool] печатать статус в конце?
    Возвращает :
      - scal               [fibo_var]

    """  

...

Снова нет ошибки в командной строке.

Обратите внимание, что если я отменяю установку PYTHONPATH в командной строке, я получаю относительную ошибку, но не совсем такую же

Ответ или решение

Устранение ошибки AttributeError в Python при запуске на веб-сервере Apache

Ваша ситуация с ошибкой AttributeError, возникающей при запуске скрипта cut_1D.py на веб-сервере Apache, связана с контекстом выполнения вашего Python-кода. Давайте разберем возможные причины этой проблемы и предложим пути её решения.

1. Понимание ошибки

Ошибка, которую вы видите в логах сервера, говорит о том, что Python не может найти атрибут from_VTK в модуле fibo. Вот сообщение об ошибке:

AttributeError: module 'fibo' has no attribute 'from_VTK'

Это может произойти по нескольким причинам:

  • Скрипт, запускаемый через Apache, использует другой интерпретатор Python с отличной от командной строки средой.
  • Неверно задан PYTHONPATH, из-за чего модуль fibo или его атрибуты недоступны.
  • Модуль fibo.py может не инициализироваться должным образом в среде веб-сервера.

2. Настройка переменной PYTHONPATH

Вы уже упомянули, что устанавливаете переменную окружения PYTHONPATH непосредственно перед выполнением скрипта. При запуске через веб-сервер PYTHONPATH может не содержать путь к вашему модулю fibo. Для устранения этой проблемы вы можете попробовать следующее:

  • Проверьте конфигурацию Apache и убедитесь, что для запуска вашего скрипта Python установлены корректные переменные окружения. Это можно сделать, добавив следующие строки в файл конфигурации Apache (например, в файле .htaccess):
SetEnv PYTHONPATH /путь/к/вашему/проекту
  • Попробуйте настроить PYTHONPATH непосредственно в вашем Python-коде:
import sys
import os

# Добавляем путь к директории, где расположен модуль fibo
sys.path.append('/полный/путь/к/вашему/проекту')

3. Проверка структуры модулей

Убедитесь, что ваша структура проекта корректна и модуль fibo действительно может быть импортирован. Ваша структура должна выглядеть следующим образом:

/путь/к/вашему/проекту/
    ├── cut_1D.py
    └── fibo/
        ├── __init__.py
        ├── mod_from.py
        └── другие_модули.py

Убедитесь, что файл __init__.py в папке fibo существует, так как он нужен для того, чтобы Python интерпретировал директорию как пакет.

4. Отладка в контексте веб-сервера

Поскольку ошибка возникает только при запуске через Apache, вам нужно:

  • Провести тестирование вашего Python-кода в среде, имитирующей настройку на сервере, например, запустив его под mod_wsgi.
  • Убедитесь, что все зависимости, используемые в вашем проекте, установлены и доступны для интерпретатора, который использует Apache. Возможно, у вас установлены разные окружения (например, виртуальные окружения), и сервер использует неправильное.

5. Логи и выводы

Проверьте логи Apache для получения дополнительной информации о потенциальных ошибках. Вывод отладки можно добавить в ваш скрипт, используя стандартное ведение логов:

import logging

logging.basicConfig(filename='/путь/к/вашему/лог-файлу.log', level=logging.DEBUG)
logging.debug('Текущий PYTHONPATH: %s', sys.path)

Заключение

Следуя указанным рекомендациям, вы сможете устранить ошибку AttributeError при выполнении вашего Python-скрипта через веб-сервер Apache. Убедитесь, что среда выполнения скрипта на сервере настроена аналогично вашей локальной среде, и проведите тщательную отладку, чтобы локализовать проблему. Если все рекомендации выполнены, а проблема сохраняется, возможно, имеет смысл перепроверить код на наличие ошибок и его совместимость с используемыми библиотеками.

Оцените материал
Добавить комментарий

Капча загружается...