即使模块实际上包含脚本,该模块也没有属性

时间:2019-05-14 20:16:46

标签: python-3.x module init attributeerror

这是我正在运行的模拟的布局

----main directory
                  -----my_script.py
                  -----settings_centroid.py
                  -----utilities (directory)
                  -----gizmo_analysis (directory)
                                                 ----gizmo_analysis.py
                                                 ----gizmo_diagnostic.py
                                                 ----gizmo_file.py
                                                 ----gizmo_ic.py
                                                 ----gizmo_io.py
                                                 ----gizmo_star.py
                                                 ----gizmo_track
                                                 ----gizmo_yield.py
                                                 ----__init__.py
                                                 ----
                  -----gizmo_read (directory)
                                             -----center.py
                                             -----constant.py
                                             -----coordinate.py
                                             -----read.py
                                             -----__init__.py

我的my_script.py是:

import gizmo_analysis
import gizmo_read
import utilities as ut
import settings_centroid

settings_centroid.init()
.
.
.

我的settings_centroid.py脚本是:

import utilities as ut
import gizmo_analysis
import rockstar_analysis
import gizmo_read

def init():
    global h, omega_m, omega_l, part, species, properties
    species, properties = 'all', 'all'    
    part=gizmo_read.read.Read.read_snapshot(species, properties, directory='./output/')
.
.
.

我的gizmo_analysis.py是:

#!/usr/bin/env python3

from __future__ import absolute_import, division, print_function  # python 2 compatability

import collections
import numpy as np
from numpy import Inf
import matplotlib
from matplotlib import pyplot as plt
from matplotlib.ticker import AutoMinorLocator
from matplotlib import colors
# local ----
import utilities as ut
import gizmo_analysis
import rockstar_analysis
import settings_centroid

settings_centroid.init()
.
.
.

我的read.py是:

# system ----
from __future__ import absolute_import, division, print_function  # python 2 compatibility
import collections
import glob
import h5py
import numpy as np
from scipy import integrate, interpolate
# local ----

from . import center, constant, coordinate
import settings_centroid
#from .. import settings_centroid

settings_centroid.init()

snapshot_index = settings_centroid.snapshot_number


# store particles as dictionary class
class DictClass(dict):
    pass


class ReadClass():
    '''
    Read Gizmo snapshot.
    '''

    def __init__(self):
        '''
        Set properties for snapshot files.
        '''
        self.snapshot_name_base = 'snap*[!txt]'  # avoid accidentally reading snapshot indices file
        self.file_extension = '.hdf5'

        self.gas_eos = 5 / 3  # gas equation of state

        # create ordered dictionary to convert particle species name to its id,
        # set all possible species, and set the order in which to read species
        self.species_dict = collections.OrderedDict()
        # dark-matter species
        self.species_dict['dark'] = 1  # dark matter at highest resolution
        self.species_dict['dark.2'] = 2  # dark matter at all lower resolutions
        # baryon species
        self.species_dict['gas'] = 0
        self.species_dict['star'] = 4

        self.species_all = tuple(self.species_dict.keys())
        self.species_read = list(self.species_all)

        # use to translate between element name and index in element table
        self.element_dict = {}
        self.element_dict['total'] = 0
        self.element_dict['he'] = 1
        self.element_dict['c'] = 2
        self.element_dict['n'] = 3
        self.element_dict['o'] = 4
        self.element_dict['ne'] = 5
        self.element_dict['mg'] = 6
        self.element_dict['si'] = 7
        self.element_dict['s'] = 8
        self.element_dict['ca'] = 9
        self.element_dict['fe'] = 10


    def read_snapshot(
        self, species='all', properties='all', directory='.', particle_subsample_factor=None):
        '''
        Read properties for input particle species from simulation snapshot file[s].
        Return particle catalog as a dictionary class.

        Parameters
        ----------
        species : string or list : name[s] of particle species:
            'all' = all species in file
            'star' = stars
            'gas' = gas
            'dark' = dark matter at highest resolution
            'dark.2' = dark matter at lower resolution
        properties : string or list : name[s] of particle properties to read - options:
            'all' = all species in file
            otherwise, list subset from among read_particles.property_dict
                for example: ['mass', 'position', 'velocity']
        directory : string : directory of snapshot file[s]
        particle_subsample_factor : int : factor to periodically subsample particles, to save memory

        Returns
        -------
        part : dictionary class : catalog of particles at snapshot
        '''

        #snapshot_index = snapshot_index  # corresponds to z = 0

        # parse input species to read
        if species == 'all' or species == ['all'] or not species:
            # read all species in snapshot
            species = self.species_all
        else:
            # read subsample of species in snapshot
            if np.isscalar(species):
                species = [species]  # ensure is list
            # check if input species names are valid
            for spec_name in list(species):
                if spec_name not in self.species_dict:
                    species.remove(spec_name)
                    print('! not recognize input species = {}'.format(spec_name))
        self.species_read = list(species)

        # read header from snapshot file
        header = self.read_header(snapshot_index, directory)

        # read particles from snapshot file[s]
        part = self.read_particles(snapshot_index, directory, properties, header)

        # assign auxilliary information to particle dictionary class
        # store header dictionary
        part.info = header
        for spec_name in part:
            part[spec_name].info = part.info

        # get and store cosmological parameters
        part.Cosmology = CosmologyClass(
            header['omega_lambda'], header['omega_matter'], hubble=header['hubble'])
        for spec_name in part:
            part[spec_name].Cosmology = part.Cosmology

        # store information about snapshot time
        time = part.Cosmology.get_time(header['redshift'], 'redshift')
        part.snapshot = {
            'index': snapshot_index,
            'redshift': header['redshift'],
            'scalefactor': header['scalefactor'],
            'time': time,
            'time.lookback': part.Cosmology.get_time(0) - time,
            'time.hubble': constant.Gyr_per_sec / part.Cosmology.get_hubble_parameter(0),
        }
        for spec_name in part:
            part[spec_name].snapshot = part.snapshot

        # adjust properties for each species
        self.adjust_particle_properties(part, header, particle_subsample_factor)

        # assign galaxy center position and velocity, principal axes rotation vectors
        self.read_galaxy_center_coordinates(part, directory)
        # alternately can assign these on the fly
        #center.assign_center(part)
        #center.assign_principal_axes(part)

        # adjust coordinates to be relative to galaxy center position and velocity
        # and aligned with principal axes
        self.adjust_particle_coordinates(part)

        return part

    def read_header(self, snapshot_index=snapshot_index, directory='.'):
        '''
        Read header from snapshot file.

        Parameters
        ----------
        snapshot_index : int : index (number) of snapshot file
        directory : directory of snapshot

        Returns
        -------
        header : dictionary class : header dictionary
        '''
        # convert name in snapshot's header dictionary to custom name preference
        header_dict = {
            # 6-element array of number of particles of each type in file
            'NumPart_ThisFile': 'particle.numbers.in.file',
            # 6-element array of total number of particles of each type (across all files)
            'NumPart_Total': 'particle.numbers.total',
            'NumPart_Total_HighWord': 'particle.numbers.total.high.word',
            # mass of each particle species, if all particles are same
            # (= 0 if they are different, which is usually true)
            'MassTable': 'particle.masses',
            'Time': 'time',  # [Gyr/h]
            'BoxSize': 'box.length',  # [kpc/h comoving]
            'Redshift': 'redshift',
            # number of output files per snapshot
            'NumFilesPerSnapshot': 'file.number.per.snapshot',
            'Omega0': 'omega_matter',
            'OmegaLambda': 'omega_lambda',
            'HubbleParam': 'hubble',
            'Flag_Sfr': 'has.star.formation',
            'Flag_Cooling': 'has.cooling',
            'Flag_StellarAge': 'has.star.age',
            'Flag_Metals': 'has.metals',
            'Flag_Feedback': 'has.feedback',
            'Flag_DoublePrecision': 'has.double.precision',
            'Flag_IC_Info': 'has.ic.info',
            # level of compression of snapshot file
            'CompactLevel': 'compression.level',
            'Compactify_Version': 'compression.version',
            'ReadMe': 'compression.readme',
        }

        header = {}  # dictionary to store header information

        if directory[-1] != '/':
            directory += '/'

        file_name = self.get_snapshot_file_name(directory, snapshot_index)

        print('reading header from:\n  {}'.format(file_name.replace('./', '')))
        print()

        # open snapshot file
        with h5py.File(file_name, 'r') as file_in:
            header_in = file_in['Header'].attrs  # load header dictionary

            for prop_in in header_in:
                prop = header_dict[prop_in]
                header[prop] = header_in[prop_in]  # transfer to custom header dict

        # convert header quantities
        header['scalefactor'] = float(header['time'])
        del(header['time'])
        header['box.length/h'] = float(header['box.length'])
        header['box.length'] /= header['hubble']  # convert to [kpc comoving]

        print('snapshot contains the following number of particles:')
        # keep only species that have any particles
        read_particle_number = 0

        species_read = list(self.species_read)
        for species_name in species_read:
            if species_name not in self.species_all:
                species_read.append(species_name)

        for spec_name in species_read:
            spec_id = self.species_dict[spec_name]
            print('  {:6s} (id = {}): {} particles'.format(
                  spec_name, spec_id, header['particle.numbers.total'][spec_id]))

            if header['particle.numbers.total'][spec_id] > 0:
                read_particle_number += header['particle.numbers.total'][spec_id]
            elif spec_name in self.species_read:
                self.species_read.remove(spec_name)

        if read_particle_number <= 0:
            raise ValueError('snapshot file[s] contain no particles of species = {}'.format(
                             self.species_read))

        print()

        return header

这是gizmo_analysis中的 init .py:

from __future__ import absolute_import  # python 2 compatability

from . import gizmo_io as io
from . import gizmo_analysis as analysis
from . import gizmo_ic as ic
from . import gizmo_diagnostic as diagnostic
from . import gizmo_file as file
from . import gizmo_track as track
from . import gizmo_star as star

这是gizmo_read中的 init .py:

#from __future__ import absolute_import  # python 2 compatability


from . import read
from . import center
from . import constant
from . import coordinate
#from .. import settings_centroid

但这是运行my_script.py时收到的错误消息:

Traceback (most recent call last):
  File "my_script.py", line 6, in <module>
    settings_centroid.init()
  File "/usr5/username/settings_centroid.py", line 9, in init
    part=gizmo_read.read.Read.read_snapshot(species, properties, directory='./output/')
AttributeError: module 'gizmo_read' has no attribute 'read'

我的理解是,我不知道脚本之间使用 inti .py而不是使用包。我确实确实希望我的主目录下的所有脚本实际上都“看到” settings_centroid.py。但是,由于某种原因,我认为目前还没有发生这种情况。在实施了Adam,Christian和J_H建议的两种不同的更改之后,我仍然收到错误消息。

3 个答案:

答案 0 :(得分:3)

编辑:在更好地理解问题后,我更改了答案。


您的问题来自循环导入(例如,参见this tutorial):您的文件settings_centroid.pygizmo_read/read.py相互包含。

当您导入settings_centroid.py时,它会导入直接运行reads.py的{​​{1}},但是在那时,Python并未加载settings_centroid.init()内的所有符号,因此找不到settings_centroid.py

圆形进口带来棘手的问题需要解决。 我的建议是重构代码以避免它们,如果您的代码库已经很大,则可能需要一些时间。

如果init()是帮助类的话,一个选项可能对整个代码的逻辑没有意义(如果没有,抱歉,您必须仔细考虑)。制作一个子包并尝试限制其对其他模块的依赖。

如果您确实无法重构,则可以 尝试 将导入限制在功能范围内。 例如,settings_centroid.py可能变为

settings_centroid.py

但是我很确定您还会遇到其他类似的问题。

希望它会有所帮助:)

答案 1 :(得分:1)

您解释说您的python3程序具有以下代码:

settings_centroid.py

import gizmo_read
...
def init():
    ...
    part=gizmo_read.read.Read.read_snapshot(...)

gizmo_read / 初始化 .py

from __future__ import absolute_import  # python 2 compatability
"""
from . import read
"""

,执行该命令将报告符号read不存在。 是的,听起来不错。 看来您从未将read.py导入该名称空间。

文档字符串就像注释一样-不会执行。

您可以通过将其附加到settings_centroid.py来进行验证:

print('centroid debug')
print('\n'.join(dir(gizmo_read)))

请注意,没有read符号。

要修复此问题,只需放弃python2 future 行, 并执行import语句,而不是将其埋入文档字符串中。

答案 2 :(得分:0)

我相信问题出在您的read.py文件中。 settings_centroid的导入语句不正确。应该是:

from .. import settings_centroid

我也不确定

from . import center, constant, coordinate

是有意的,除非没有代码在“ gizmo_read”模块中看不到。尝试解决这些错误,导入应该可以进行。