5
#!/bin/perl 
use Inline Python; 
$s = new Sun(); 
print "SUN: $s\n"; 
$m = new Moon(); 
__END__ 
__Python__ 
from ephem import Sun as Sun; 
from ephem import Moon as Moon; 

The code above yields:

SUN: <Sun "Sun" at 0x9ef6f14>
Can't bless non-reference value at /usr/local/lib/perl5/site_perl/5.10.0/i386-linux-thread-multi/Inline/Python.pm line 317.

What's wrong? I've tried this with many other objects (eg:

from ephem import Observer as Observer;

and then

$o= new Observer();

in the body of my code) and it works fine for everything I've tried EXCEPT Moon.

EDIT (probably useless information):

In https://github.com/brandon-rhodes/pyephem/tree/master/libastro-3.7.5 :

  • The routines for calculating Sun, Mercury, Venus, Mars (the ones that work fine) are done in vsop87.c, function vsop87()

  • The routines for calculating Jupiter, Saturn, etc (the ones that don't work) are done in chap95.c, function chap95()

  • vsop87() "returns" an array of 6 doubles, which appear to be some sort of spherical coordinates.

  • chap95() "returns" an array of 6 doubles, which appear to be Cartesian coordinates, ie, rectangular and NOT spherical.

  • planpos() in plans.c calls one of the two functions above, depending on which planet you choose. What's odd is that planpos() treats the function results the same (sort of), even though they return very different things.

  • After planpos(), all planets are treated the same. planpos() is called by plans() (also in plans.c), which is in turn called by obj_planet() in circum.c which is then called by obj_cir() also in circum.c

  • obj_planet() and obj_cir() define the planet. Since planets are treated the same after planpos(), there should be no difference between them.

Lok Jun
1,3433 gold badges9 silver badges16 bronze badges
asked Nov 27, 2013 at 5:59
4
  • Jupiter and Saturn also do not work, but Mercury and Venus work. The three non-working are somehow special-cased in the python code. Commented Nov 27, 2013 at 7:01
  • I also tried Mars earlier, and it works. I don't know if there IS any Python code... I think the Python stuff is just bindings to a C library, libastro. Commented Nov 27, 2013 at 16:05
  • There's some glue python code, on my system in /usr/local/lib/python2.7/site-packages/ephem/__init__.py. I see special handling for Moon, Jupiter, and Saturn there. The comment says "We now replace two of the classes we have just created, because _libastro actually provides separate types for two of the bodies." Commented Nov 28, 2013 at 1:16
  • @SlavenRezic You are correct. Sadly, "from ephem import _libastro.Moon as Moon;" doesn't work either. Commented Nov 28, 2013 at 2:49

1 Answer 1

0

It is indeed the different handling for the Moon, Jupiter and Saturn bodies, as pointed out by Slaven in the comments. In fact, you're running into the Python 2 issue that there is a difference between types and classes. I can't give you the details, but there is quite a bit of material on the subject.

Suffice to say, that the Python wrapper provided by PyEphem turns the bodies into a proper class, which Python::Inline can handle. The Python-C wrapper, _libastro, provides types instead, and thus setting Moon to _libastro.Moon makes Moon a type instead of a class. Why Python::Inline can deal with classes and not types, I don't know.

This, however, provides enough information for a work-around: turn ephem.Moon into a class. Thus, the following may work:

#!/usr/bin/env perl
use Inline Python; 
$s = new Sun(); 
print "SUN: $s\n"; 
$m = new Moon(); 
print "Moon: $m\n";
__END__ 
__Python__ 
from ephem import Sun
from ephem import Moon
class Moon(Moon):
 pass

which for me results in:

SUN: <Sun "Sun" at 0x1f450b0>
Moon: <Moon "Moon" at 0x20eec50>

You can apply the same trick to Saturn and Jupiter of course.

(I've "Pythonized" the import statements a bit: no need for as or semi-colons.)

In case you'd like to verify that the Moon is still a special body even after turning it into a class, try to use on of its special attributes, for example libration_lat:

$m->compute()
$mllat = $m->{libration_lat};
print "Moon: ${mllat}\n";
Moon: 5:50:29.6

which will fail for any other type such as the Sun.

(I found these special attributes in test_bodies.py in the PyEphem package, though I presume these are documented as well. In case you'd like to test for Saturn and Jupiter, you can find them there.)

answered Feb 10, 2014 at 12:46
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thanks! In the interim, I discovered Skyfield... now, how to use that in Perl, hmmm.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.