i have basic python agi code with pyst lib as:
extensions.conf
[from-internal]
exten => _.,1,answer()
exten => _.,2,AGI(test.py)
i have test.py in /var/lib/asterisk/agi-bin as
#!/usr/bin/python
import sys
import os
from agi import AGI
def test_call(agi = None,text = ""):
agi.say_alpha(text, "#")
agi.hangup()
if __name__ == "__main__":
text = 'abcdefr'
agi = AGI()
test_call(agi,text)
and i have one file agi.py which is get from pyst lib.
when i try to call to this agi i get this issue
Executing [123#from-internal:1] Answer("SIP/12345-00000016", "") in new stack
[Mar 14 00:01:29] NOTICE[2790]: res_rtp_asterisk.c:2358 ast_rtp_read: Unknown RTP codec 126 received from '169.254.38.82:20338'
-- Executing [123#from-internal:2] AGI("SIP/12345-00000016", "test.py") in new stack
-- Launched AGI Script /var/lib/asterisk/agi-bin/test.py
test.py: Failed to execute '/var/lib/asterisk/agi-bin/test.py': No such file or directory
-- Auto fallthrough, channel 'SIP/12345-00000016' status is 'UNKNOWN'
-- Executing [h#from-internal:1] Hangup("SIP/12345-00000016", "") in new stack
== Spawn extension (from-internal, h, 1) exited non-zero on 'SIP/12345-00000016'
i see that i have this file in /var/lib/asterisk/agi-bin which 777 permission.
Please suggest to get this basic script work.
thank all in advance
There can be 2 reason for such error:
no file /var/lib/asterisk/agi-bin/test.py in that location or it not accessable by asterisk for some reason - linux general permission issue.
file /var/lib/asterisk/agi-bin/test.py, but no some libraries(python give same error). This one is more likly. Try execute script manual from asterisk user and see what it say.
Recomendation: Use FastAGI instead of AGI.
Related
I am using a raspberry pi 4 mode B to interface communicate with a Teensy 4.0. I'm using ROS noetic on Ubuntu 20.04. I've flashed the code to the Teensy successfully using platformio. I have a problem, however, when I try and launch the calibration python script for the robot I'm working on. I'm interfacing the raspberry Pi with the Teensy through the GPIO pins (this is after I've flashed the code to the Teensy, I flashed it through usb). When I run the calibration script using roslaunch mini_ros spot_calibration I get the following error:
[servo_calibration-1] process has died [pid 4841, exit code 1, cmd /home/ubuntu/spark_ws/src/spot_mini_mini/mini_ros/src/servo_calibration __name:=servo_calibration __log:=/home/ubuntu/.ros/log/fa068172-32ea-11ec-b45a-513494152363/servo_calibration-1.log].
log file: /home/ubuntu/.ros/log/fa068172-32ea-11ec-b45a-513494152363/servo_calibration-1*.log
[ERROR] [1634874547.846356]: Mismatched protocol version in packet (b'\xf8'): lost sync or rosserial_python is from different ros release than the rosserial client
below is the python code in spot_calibration
#!/usr/bin/env python
"""
DESCRIPTION:
SUBSCRIBERS:
"""
from __future__ import division
import rospy
from mini_ros.srv import CalibServo, CalibServoResponse
from mini_ros.msg import JointPulse
import numpy as np
import sys
import rospkg
rospack = rospkg.RosPack()
sys.path.append(rospack.get_path('mini_ros') + '/../')
sys.path.append('../../')
class ServoCalibrator():
def __init__(self):
rospy.init_node('ServoCalibrator', anonymous=True)
self.serv = rospy.Service('servo_calibrator', CalibServo,
self.calib_service_cb)
self.jp_pub = rospy.Publisher('spot/pulse', JointPulse, queue_size=1)
def calib_service_cb(self, req):
""" Requests a servo to be moved to a certain position
Args: req
Returns: response
"""
try:
jp_msg = JointPulse()
jp_msg.servo_num = req.servo_num
jp_msg.servo_pulse = req.servo_pulse
self.jp_pub.publish(jp_msg)
response = "Servo Command Sent."
except rospy.ROSInterruptException:
response = "FAILED to send Servo Command"
return CalibServoResponse(response)
def main():
""" The main() function. """
srv_calib = ServoCalibrator()
rospy.loginfo(
"Use The servo_calibrator service (Pulse Width Unit is us (nominal ~500-2500))."
)
while not rospy.is_shutdown():
rospy.spin()
if __name__ == '__main__':
try:
main()
except rospy.ROSInterruptException:
pass
The package was supposedly made in ROS Melodic, so that might be why it's throwing the error, but I don't know what to change if the package is melodic exclusive.
The problem is indeed because the roslib package used by rosserial was build for Melodic. As you can guess this error is just caused because of mismatched version ids coming from the arduino side. The best option would be to rebuild ros_lib for Noetic.
To rebuild ros_lib all you have to do is navigate to your sketchbook and run make_libraries.py. Note that this will build up to the currently installed distro, so you need to run this on a machine that has Noetic installed.
cd <sketchbook>/libraries
rm -rf ros_lib
rosrun rosserial_arduino make_libraries.py .
If rebuilding isn't an option you can add the definitions manually. On the arduino side you'll have a ros_lib folder. You have two sub directories you need to change.
The first is ./ros/node_handle.h. At the top of the file you'll see a few protocol versions defined as const uint8_t. Add in the version id for noetic as const uint8_t PROTOCOL_VER6 = 0xfa; then change the line that states what version should be used. const uint8_t PROTOCOL_VER = PROTOCOL_VER6;.
Lastly, you just need to make this same change in ./ros_lib/ros/node_handle.h
I am trying to use ALDialog module to have a virtual conversation with the Choregraphe simulated NAO6 robot. I have the below script:
import qi
import argparse
import sys
def main(session):
"""
This example uses ALDialog methods.
It's a short dialog session with two topics.
"""
# Getting the service ALDialog
ALDialog = session.service("ALDialog")
ALDialog.setLanguage("English")
# writing topics' qichat code as text strings (end-of-line characters are important!)
topic_content_1 = ('topic: ~example_topic_content()\n'
'language: enu\n'
'concept:(food) [fruits chicken beef eggs]\n'
'u: (I [want "would like"] {some} _~food) Sure! You must really like $1 .\n'
'u: (how are you today) Hello human, I am fine thank you and you?\n'
'u: (Good morning Nao did you sleep well) No damn! You forgot to switch me off!\n'
'u: ([e:FrontTactilTouched e:MiddleTactilTouched e:RearTactilTouched]) You touched my head!\n')
topic_content_2 = ('topic: ~dummy_topic()\n'
'language: enu\n'
'u:(test) [a b "c d" "e f g"]\n')
# Loading the topics directly as text strings
topic_name_1 = ALDialog.loadTopicContent(topic_content_1)
topic_name_2 = ALDialog.loadTopicContent(topic_content_2)
# Activating the loaded topics
ALDialog.activateTopic(topic_name_1)
ALDialog.activateTopic(topic_name_2)
# Starting the dialog engine - we need to type an arbitrary string as the identifier
# We subscribe only ONCE, regardless of the number of topics we have activated
ALDialog.subscribe('my_dialog_example')
try:
raw_input("\nSpeak to the robot using rules from both the activated topics. Press Enter when finished:")
finally:
# stopping the dialog engine
ALDialog.unsubscribe('my_dialog_example')
# Deactivating all topics
ALDialog.deactivateTopic(topic_name_1)
ALDialog.deactivateTopic(topic_name_2)
# now that the dialog engine is stopped and there are no more activated topics,
# we can unload all topics and free the associated memory
ALDialog.unloadTopic(topic_name_1)
ALDialog.unloadTopic(topic_name_2)
if __name__ == "__main__":
session = qi.Session()
try:
session.connect("tcp://desktop-6d4cqe5.local:9559")
except RuntimeError:
print ("\nCan't connect to Naoqi at IP desktop-6d4cqe5.local(port 9559).\nPlease check your script's arguments."
" Run with -h option for help.\n")
sys.exit(1)
main(session, "desktop-6d4cqe5.local")
My simulated robot has desktop-6d4cqe5.local as IP address and its NAOqi port is running on 63361. I want to run the dialogs outside of the Choregraphe in a python script and only be able to use the dialog box within the Choregraphe to test it. When I ran the above python file I got:
Traceback (most recent call last):
File "C:\Users\...\Documents\...\choregraphe_codes\Welcome\speak.py", line 6, in <module>
import qi
File "C:\Python27\Lib\site-packages\pynaoqi\lib\qi\__init__.py", line 93
async, PeriodicTask)
^
SyntaxError: invalid syntax
I couldn't figure out the problem as there was not much resources online and the robot's documentations are a bit hard to understand.
Please help, thank you.
You are running the script using a Python version greater than 3.5, that sees async as a keyword, now.
NAOqi only supports Python 2.
Try running your script with python2 explicitly.
My py2app build displays an error message with a Terminate button when the app is launched with a double-click. However, if I open it directly in Terminal then it works perfectly well. All of the following Terminal commands launch the app successfully:
# .MyApp.app/Contents/MacOS/MyApp
# open MyApp.app
# open -a MyApp.app
I've read several posts about similar py2app errors but I can't figure out what could be the issue here. The problem seems to have been around for at least four years, is not specific to py2app and seems related to a general issue with Python on macOS. Users of pyinstaller are reporting the exact same problem with no obvious solution in sight AFAIK.
My setup.py file:
from setuptools import setup
APP = ['myapp.py']
DATA_FILES = [('img', ['img/myapp-logo.png']), ('data', ['data/data.yml'])]
OPTIONS = {'iconfile': 'icon.icns'}
setup(
app=APP,
name='My App',
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
The macOS Console shows the following message in system.log: com.apple.xpc.launchd[1] (org.pythonmac.unspecified.MyApp.4952[16783]): Service exited with abnormal code: 255
Suspect 1: file access?
This thread on the pyinstaller GitHub issues page has multiple people reporting the same error with no clear fix. This proposed solution seems related to the working directory issues described in the pyinstaller thread but doesn't solve the problem on my system.
My app is only reading a single yml file from its working directory and doesn't write anything to disk. It is nothing more than a simple file access statement:
file = os.path.realpath('data/data.yml')
with open(file) as f:
# etc
In Catalina, I've added the app to the list of apps allowed Full Disk Access in the Security Preferences but this doesn't solve the issue either (it would have been surprising if it did, though, since the open command works as mentioned above).
Suspect 2: Tkinter?
This thread on pyinstaller GitHub suggests the problem might be related to a Tkinter version. The proposed solution seems to have fixed the issue for some users. However, on my end I have a working app bundle from an earlier version, before adding the open file statement, which launches just fine when double clicked.
Suspect 1 vs 2
I have forked my code into two branches, one completely removing references to Tkinter, the other removing file access in favour of initialisation via variables in the code. The crash does not happen in the second case. This would seem to rule out Tkinter as the source of the problem, although weirdly enough a hack to Tkinter has fixed it for other users.
macOS versions
I've tested both bundle versions (working and not working) on both Catalina 10.15.6 and El Capitan 10.11.6 and the behaviour is identical.
The Firing of the Death Sentinel
Here's what the Console log looks like after launching the app normally through the Finder:
default 21:26:13.836380+0200 runningboardd Acquiring assertion targeting executable<MyPythonApplication(501)> from originator [daemon<com.apple.coreservices.launchservicesd>:165] with description <RBSAssertionDescriptor; frontmost:27280; ID: 391-165-34219; target: 27280> attributes = {
<RBSDomainAttribute: 0x7f9f1a712910; domain: com.apple.launchservicesd; name: RoleUserInteractiveFocal; sourceEnvironment: 0x0>;
}
default 21:26:13.836649+0200 runningboardd Assertion 391-165-34219 (target:executable<MyPythonApplication(501)>) will be created as active
default 21:26:13.838258+0200 runningboardd [executable<MyPythonApplication(501)>:27280] Ignoring jetsam update because this process is not memory-managed
default 21:26:13.839703+0200 runningboardd [executable<MyPythonApplication(501)>:27280] Set darwin role to: UserInteractiveFocal
default 21:26:13.840634+0200 runningboardd [executable<MyPythonApplication(501)>:27280] Ignoring GPU update because this process is not GPU managed
default 21:26:13.840912+0200 runningboardd Finished acquiring assertion 391-165-34219 (target:executable<MyPythonApplication(501)>)
default 21:26:15.166436+0200 hidd Connection removed: IOHIDEventSystemConnection uuid:B1D40AB3-FD55-455C-9E1B-2E4C4C6E4982 pid:27280 process:MyPythonApplication type:Passive entitlements:0x0 caller:HIToolbox: ___GetIOHIDEventSystemClient_block_invoke + 26 attributes:(null) state:0x1 events:0 mask:0x0
default 21:26:15.171128+0200 runningboardd [executable<MyPythonApplication(501)>:27280] Death sentinel fired!
default 21:26:15.174315+0200 runningboardd Invalidating assertion 391-165-34219 (target:executable<MyPythonApplication(501)>) from originator 165
default 21:26:15.176832+0200 loginwindow -[PersistentAppsSupport applicationQuit:] | for app:MyPythonApplication, _appTrackingState = 2
default 21:26:15.176856+0200 loginwindow -[PersistentAppsSupport applicationQuit:] | App: MyPythonApplication, quit, updating active tracking timer
default 21:26:15.179589+0200 runningboardd Invalidating assertion 391-165-34209 (target:executable<MyPythonApplication(501)>) from originator 165
default 21:26:15.281529+0200 runningboardd Removing process: [executable<MyPythonApplication(501)>:27280]
default 21:26:15.282124+0200 runningboardd Removing assertions for terminated process: [executable<MyPythonApplication(501)>:27280]
error 21:26:15.292603+0200 runningboardd RBSStateCapture remove item called for untracked item 391-165-34209 (target:executable<MyPythonApplication(501)>)
error 21:26:15.292622+0200 runningboardd RBSStateCapture remove item called for untracked item 391-165-34219 (target:executable<MyPythonApplication(501)>)
Apparently the error is mentioned in this line, in case someone can make anything out of it:
hidd Connection removed: IOHIDEventSystemConnection uuid:foo pid:bar process:MyPythonApplication type:Passive entitlements:0x0 caller:HIToolbox: ___GetIOHIDEventSystemClient_block_invoke + 26 attributes:(null) state:0x1 events:0 mask:0x0
This is immediately followed by RunningBoard firing the Death Sentinel, whatever this entity might be. The system is described in this article by Howard Oakley but it is way beyond my level of expertise.
Some more info gathered by Ulbow confirms an error with the highly informative message "MacOS error: -67062":
com.apple.runningboard 4941060 391 Received message from [daemon<com.apple.coreservices.launchservicesd>:165] (euid 0): acquireAssertionWithDescriptor:error:
com.apple.launchservices 4940599 802 OSStatus _LSLaunch(LSContext *, FSNode *, LSLaunchFlags, void *, CFArrayRef, const AppleEvent *, const AEDescList *, CFArrayRef, CFDictionaryRef, LSBundleID, const audit_token_t *, const _LSOpen2Options *, ProcessSerialNumber *, Boolean *, NSError **): launching '<private>' result=0
com.apple.securityd 9807 904 MacOS error: -67062
com.apple.runningboard 4941063 391 Received message from [daemon<com.apple.coreservices.launchservicesd>:165] (euid 0): acquireAssertionWithDescriptor:error:
com.apple.sharedfilelist 4940599 802 -[SFLGenericList _insertItem:atIndex:error:]_block_invoke com.apple.LSSharedFileList.RecentApplications
com.apple.securityd 4940933 530 UNIX error exception: 8
4941117 27642 MyPythonApplication Error
com.apple.securityd 4941064 165 UNIX error exception: 22
com.apple.securityd 4941064 165 MacOS error: -67062
com.apple.runningboard 4941002 391 Received message from [daemon<com.apple.coreservices.launchservicesd>:165] (euid 0): acquireAssertionWithDescriptor:error:
com.apple.securityd 4941161 198 MacOS error: -67062
com.apple.TCC 4941161 198 Failed to copy signing info for 27642, responsible for file:///Users/me/Files/Docs/Code/Python/MyPythonApplication/dist/MyPythonApplication.app/Contents/MacOS/Pandemic%20Deck%20Tracker: #-67062: Error Domain=NSOSStatusErrorDomain Code=-67062 "(null)"
com.apple.securityd 4941161 198 MacOS error: -67062
com.apple.securityd 4941161 198 MacOS error: -67062
com.apple.launchservices 4941064 165 CLIENT: 0x7fcec00b33b0/27642 Received XPC_ERROR on connection from our client, so invalidating it and our connection.
com.apple.appleevents 4941120 462 CONNECTION: peer=? peer-pid=27642 got event (Error "Connection invalid")
com.apple.appleevents 4941120 462 CONNECTION: Recevied XPC_ERROR on a connection from 27642, a client of ours, so unregistering any application with that pid.
com.apple.appleevents 4941120 462 CONNECTION: releasing app App:"MyPythonApplication"/"MyPythonApplication"/"org.pythonmac.unspecified.MyPythonApplication" 27642/0x0:0x308d08a ????1010 sess=100020 because we received error on its connection.
com.apple.runningboard 4941002 391 Received message from [daemon<com.apple.coreservices.launchservicesd>:165] (euid 0): acquireAssertionWithDescriptor:error:
Several exchanges on recent tests, trying to pinpoint the cause for the bug, can be found on this GitHub issues page, but it still remains a mystery (and a very bizarre one, too).
An Apple engineer should really take a look at this.
A pretty thorough investigation of this issue has been conducted on this GitHub issue page by the maintainers of pyinstaller. It turns out that if a Python script accesses resources on a macOS file system using the built-in Python os module, the app bundle crashes. The bundle does not crash if the script is run directly from a Terminal command.
The proposed solution is to check if the script is running on macOS and, in that case, use AppKit to open the file. This requires installing the pyobjc module but otherwise it is not a major hassle.
Instead of doing this:
import os
file = os.path.realpath('path/somefile.ext')
with open(file) as f:
# ...
Do this:
import os
import platform
def get_path(filename):
name = os.path.splitext(filename)[0]
ext = os.path.splitext(filename)[1]
if platform.system() == "Darwin":
from AppKit import NSBundle
file = NSBundle.mainBundle().pathForResource_ofType_(name, ext)
return file or os.path.realpath(filename)
else:
return os.path.realpath(filename)
file = get_path('path/somefile.ext')
with open(file) as f:
# ...
I can confirm this works on macOS Catalina with pyinstaller. I haven't had the chance to test this on .exe builds for Windows.
After hours of digging I finally found an answer! Even after every Step I count gain the right /Contents/Resources path.
First I had to get this working:
from AppKit import NSBundle
file = NSBundle.mainBundle().pathForResource_ofType_(name, ext)
For my Python App, finding the "AppKit" module I had to install
pip install pyobjc
But even then, the path for
NSBundle.mainBundle().pathForResource_ofType_(name, ext)
was strange. It was a path in "/private/var/" where I don't have Write Access
The final answer was to run
xattr -d com.apple.quarantine /Applications/YouPythonApp.app/
then I finally got the right path
/Applications/YouPythonApp.app/Contents/Resources/
where I also had write access and now I can save my .yaml file
with open(file, "w") as f:
yaml=YAML()
yaml.default_flow_style = False
yaml.dump(config, f)
It is the first time I write as I really didn't find any solution to my issue.
I want to allow my user to launch some Python program from Excel.
So i have this VBA code at some point:
lg_ErrorCode = wsh.Run(str_PythonPath & " " & str_PythonArg, 1, bl_StopVBwhilePython)
If lg_ErrorCode <> 0 Then
MsgBox "Couldn't run python script! " _
+ vbCrLf + CStr(lg_ErrorCode)
Run_Python = False
End If
str_PythonPath = "C:\Python34\python.exe C:\Users\XXXX\Documents\4_Python\Scan_FTP\test.py"
str_PythonArg = "arg1 arg2"
After multiple testing, the row in error in Python is when I try to import another module (I precise that this VBA code is working without the below row in Python):
import fct_Ftp as ftp
The architecture of the module is as follow:
4_Python
-folder: Scan_FTP
- file: test.py (The one launch from VBA)
-file: fct_Ftp.py
(For information, I change the architecture of the file, and try to copy the file at some other position just to test without success)
The import has no problem when I launch Test.py directly with:
import sys, os
sys.path.append('../')
But from VBA, this import is not working.
So I figured out this more generic solution, that dont work as well from Excel/VBA
import sys, os
def m_importingFunction():
str_absPath = os.path.abspath('')
str_absPathDad = os.path.dirname(str_absPath)
l_absPathSons = [os.path.abspath(x[0]) for x in os.walk('.')]
l_Dir = l_absPathSons + [str_absPathDad]
l_DirPy = [Dir for Dir in l_Dir if 'Python' in Dir]
for Dir in l_DirPy:
sys.path.append(Dir)
print(Dir)
m_importingFunction()
try:
import fct_Ftp as ftp
# ftp = __import__ ("fct_Ftp")
write += 'YAAAA' # write a file YAAAA from Python
except:
write += 'NOOOOOO' # write a file NOOOOO from VBA
f= open(write + ".txt","w+")
f.close()
Can you please help me as it is a very tricky questions ?
Many thanks to you guys.
You are able to start your program from the command line?
Why not create a batch file with excel which you then start in a shell?
I'm creating a really basic program that simulates a terminal with Python3.6, its name is Prosser(The origin is that "Prosser" sounds like "Processer" and Prosser is a command processer).
A problem that I'm having is with command import, this is, all the commands are stored in a folder called "lib" in the root folder of Prosser and inside it can have folders and files, if a folder is in the "lib" dir it can't be named as folder anymore, its name now is package(But this doesn't care for now).
The interface of the program is just a input writed:
Prosser:/home/pedro/documents/projects/prosser/-!
and the user can type a command before the text, like a normal terminal:
Prosser:/home/pedro/documents/projects/prosser/-! console.write Hello World
let's say that inside the "lib" folder exists one folder called "console" and inside it has a file called "write.py" that has the code:
class exec:
def main(args):
print(args)
As you can see the first 2 lines is like a important structure for command execution: The class "exec" is the main class for the command execution and the def "main" is the main and first function that the terminal will read and execute also pass the arguments that the user defined, after that the command will be responsible to catch any error and do what it will be created to do.
At this moment, everything is ok, but now comes the true help that I need of U guys, the command import.
Like I writed the user can type any command, and in the example above I typed a "console.write Hello World" and exists one folder called "console" and one file "write.py". The point is that the packages can be defined by a "dot", this is:
-! write Hello World
Above I only typed "write" and this says that the file is only inside the "lib" folder, it doesn't has a package to storage and separate it, so it is a Freedom command(A command that doesn't has packages or nodes).
-! console.write Hello World
Now I typed above "console.write" and this says that the file has a package or node to storage and separate it, this means that it is a Tied command(A command that has packages or nodes).
With that, a file is separated from the package(s) with a dot, the more dots you put, more folders will be navigated to find the file and proceed to the next execution.
Code
Finnaly the code. With the import statement I tryied this:
import os
import form
curDir = os.path.dirname(os.path.abspath(__file__)) # Returns the current direrctory open
while __name__ == "__main__":
c = input('Prosser:%s-! ' % (os.getcwd())).split() # Think the user typed "task.kill"
path = c[0].split('.') # Returns a list like: ["task", "kill"]
try:
args = c[1:] # Try get the command arguments
format = form.formater(args) # Just a text formatation like create a new line with "$n"
except:
args = None # If no arguments the args will just turn the None var type
pass
if os.path.exists(curDir + "/lib/" + "/".join(path) + ".py"): # If curDir+/lib/task/kill.py exists
module = __import__("lib." + '.'.join(path)) # Returns "lib.task.kill"
module.exec.main(args) # Execute the "exec" class and the def "**main**"
else:
pathlast = path[-1] # Get the last item, in this case "kill"
path.remove(path[-1]) # Remove the last item, "kill"
print('Error: Unknow command: ' + '.'.join(path) + '. >>' + pathlast + '<<') # Returns an error message like: "Error: Unknow command: task. >>kill<<"
# Reset the input interface
The problem is that when the line "module = __import__("lib." + '.'.join(path))" is executed the console prints the error:
Traceback (most recent call last):
File "/home/pedro/documents/projects/prosser/main.py", line 18, in <module>
module.exec.main(path) # Execute the "exec" class and the def "**main**"
AttributeError: module 'lib' has no attribute 'exec'
I also tried to use:
module = \_\_import\_\_(curDir + "lib." + '.'.join(path))
But it gets the same error. I think it's lighter for now. I'd like if someone help me or find some replacement of the code. :)
I think you have error here:
You have diffirent path here:
if os.path.exists(curDir + "/lib/" + "/".join(path) + ".py")
And another here, you dont have curDir:
module = __import__("lib." + '.'.join(path)) # Returns "lib.task.kill"
You should use os.path.join to build paths like this:
module = __import__(os.path.join(curdir, 'lib', path + '.py'))